如何解决未定义的行为在C中串联字符串
我正在编写一个C语言程序,该程序将连接所有行(包括“ \n
”),同时将指针保存到最终字符串的最后一个字符。但是,我没有得到预期的结果。可能是什么问题?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
struct Node *next;
struct Node *prev;
};
struct Node *CreateNewNode() {
struct Node *newNode = malloc(sizeof(struct Node));
return newNode;
}
struct PieceTable {
char *buffer;
char *ptr_to_last_character;
} PT;
void strconcatenate(char *source) {
size_t source_len = strlen(source);
size_t buffer_len = strlen(PT.buffer);
PT.buffer = realloc(PT.buffer,buffer_len + source_len + 1);
while (*source)
*PT.ptr_to_last_character++ = *source++;
*PT.ptr_to_last_character = '\0';
}
int main(int argc,char *argv[]) {
char input_line[1024];
PT.buffer = malloc(sizeof(char) * 2);
*PT.buffer = '\0';
PT.ptr_to_last_character = PT.buffer;
struct Node *new_node = CreateNewNode();
new_node->next = NULL;
new_node->prev = NULL;
strconcatenate("Lorem ipsum\n");
strconcatenate("dolor sit amet\n");
strconcatenate("consectetur adipiscing elit\n");
printf("%s",PT.buffer);
return 0;
}
预期输出:
Lorem ipsum
dolor sit amet
consectetur adipiscing elit
输出:
etur adipiscing elit
解决方法
您重新分配了PT.buffer
,但没有更新PT.ptr_to_last_character
。当realloc
不能只是扩展当前分配,而是在另一个地址返回一个新的较大区域,而使ptr_to_last_character
指向旧内存时,则会导致未定义的行为。
可能更好的方法是存储缓冲区的长度,而不是存储指向最后一个字符的指针,这样您就不必担心使其无效。
,注意事项: Paul已经找到了问题,但是由于您说您需要一个指针...
您可以通过保存/恢复偏移量来调整“最后一个”指针:
raise exception_class(message,screen,stacktrace)
selenium.common.exceptions.WebDriverException: Message:
我在下面的完整代码中注释了其他一些清理问题。 ptrdiff_t offset = PT.ptr_to_last_character - PT.buffer;
PT.buffer = realloc(PT.buffer,buffer_len + source_len + 1);
PT.ptr_to_last_character = PT.buffer + offset;
包装旧的/原始的代码。 #if 0
包装新的/重构的代码:
#if 1
,
对于初学者来说,不清楚为什么在此语句中分配两个字节而不是一个字节。
PT.buffer = malloc(sizeof(char) * 2);
*PT.buffer = '\0';
在函数中此语句
size_t buffer_len = strlen(PT.buffer);
考虑到您已经有一个指向终止零的指针,没有任何意义。因此效率很低。
在致电realloc
PT.buffer = realloc(PT.buffer,buffer_len + source_len + 1);
指针PT.ptr_to_last_character
可能无效。
还应该检查内存分配是否成功。否则,如果发生故障,指针PT.buffer
可以设置为NULL。
该功能可以通过以下演示程序中所示的以下方式实现。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct PieceTable {
char *buffer;
char *ptr_to_last_character;
} PT;
int strconcatenate( const char *source )
{
int success = 1;
size_t n = PT.ptr_to_last_character - PT.buffer;
size_t source_len = strlen( source );
if ( source_len != 0 )
{
char *tmp = realloc( PT.buffer,n + source_len + 1 );
if ( ( success = tmp != NULL ) )
{
PT.buffer = tmp;
PT.ptr_to_last_character = PT.buffer + n;
while ( ( *PT.ptr_to_last_character = *source++ ) ) ++PT.ptr_to_last_character;
}
}
return success;
}
int main(void)
{
PT.buffer = malloc( sizeof(char) );
*PT.buffer = '\0';
PT.ptr_to_last_character = PT.buffer;
strconcatenate( "Lorem ipsum\n" );
strconcatenate( "dolor sit amet\n" );
strconcatenate( "consectetur adipiscing elit\n" );
puts( PT.buffer );
return 0;
}
程序输出为
Lorem ipsum
dolor sit amet
consectetur adipiscing elit
还要考虑到这一点,而不是手动编写的循环
while ( ( *PT.ptr_to_last_character = *source++ ) ) ++PT.ptr_to_last_character;
您可以使用效率更高的标准C字符串函数strcat
或strcpy
。
在这种情况下,您可以通过以下方式查看功能
int strconcatenate( const char *source )
{
int success = 1;
size_t n = PT.ptr_to_last_character - PT.buffer;
size_t source_len = strlen( source );
if ( source_len != 0 )
{
char *tmp = realloc( PT.buffer,n + source_len + 1 );
if ( ( success = tmp != NULL ) )
{
PT.buffer = tmp;
PT.ptr_to_last_character = PT.buffer + n;
strcpy( PT.ptr_to_last_character,source );
PT.ptr_to_last_character += source_len;
}
}
return success;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。