我一直被困在这个上,我不是C的专家。基本上,我正在尝试制作一个“安全地”将角色划分到现有角色*的功能。
我试图从这个例子中获得“动态分配”方法:
我做了一些修改,我删除了由realloc函数设置的var(编译器说它返回了void)。我还修改它只附加一个字符而不是一个字符数组。我认为这会改变“realloc”参数,所以不是传递加法字符串的长度,而是传入“sizeof(char)”(x2,因为原来有一个额外的sizeof char,我想是因为null终止符?)
char *buffer = NULL;
int mystrcat(char addition)
{
realloc(buffer, strlen(buffer) + sizeof(char)*2);
if (!buffer)
return 0;
strcat(buffer, addition);
return 1;
}
我称之为:
if(!safestrcat(str[i+j]))
printf("Out of Memory");
出于某种原因,我看到了这一点:
myProg.exe中0x60f0d540(msvcr100d.dll)的未处理异常: 0xC0000005:访问冲突读取位置0x00000000。
调试器在第81行显示strlen.asm:
main_loop:
mov eax,dword ptr [ecx] ; read 4 bytes
如果这是一个新问题,我很抱歉,但是发生了什么?为什么添加char没有附加到缓冲区?
抱歉,我应该补充说,它成功编译。
答案 0 :(得分:6)
sizeof(char)
为1 realloc
代码已损坏strcat
不会将char
作为其第二个参数strcat
做char* mystrcat(char* buffer, char addition) {
unsigned oldlen = strlen(buffer);
buffer = realloc(buffer, oldlen + 2);
if (buffer == NULL)
return NULL;
buffer[oldlen + 0] = addition;
buffer[oldlen + 1] = '\0';
return buffer;
}
然而,请注意两件事:
mystrcat
- 与strcat
相同!如果失败,函数返回NULL
- 在这种情况下,调用者有责任确保释放原始缓冲区的内存。这意味着您不能将该函数称为
buffer = mystrcat(buffer, 'x');
- 这可能会导致内存泄漏。
所以正确的用法是:
char* something = "hello";
char* buffer = malloc(sizeof(something) + 1);
strcpy(buffer, something);
char* new_buffer = mystrcat(buffer, 'x');
if (new_buffer == NULL) {
free(buffer);
exit(1);
}
buffer = new_buffer;
是的,令人费解。这是安全记忆操作的代价。
答案 1 :(得分:2)
您对realloc的调用完全被破坏 - 您需要检查是否成功,然后将函数的结果重新分配给现有指针。
您还需要char *
作为第二个参数传递给strcat
,而不是char
。
变化:
int mystrcat(char addition)
{
realloc(buffer, strlen(buffer) + sizeof(char)*2);
if (!buffer)
return 0;
strcat(buffer, addition);
return 1;
}
为:
int mystrcat(char addition)
{
char st[2] = { addition, '\0' }; // make temporary string to hold `addition`
int len = buffer != NULL ? strlen(buffer) : 0; // NB: handle case where `buffer` has not yet been allocated
char * tmp = realloc(buffer, len + 2); // increase size of `buffer`
if (!tmp) // handle realloc failure
return 0;
buffer = tmp;
strcat(buffer, st); // append `addition`
return 1;
}
答案 2 :(得分:2)
其他答案中给出了很多非常好的建议,但是您获得访问冲突的原因是因为buffer
以NULL
开头。然后你做strlen(buffer)
。 strlen()
通过计算从传入的地址开始直到达到'\0'
的字符为止。所以在你的情况下,第一次,你取消引用空指针。
答案 3 :(得分:1)
char * mystrcat(char *str, char addition)
{
size_t len;
len = strlen(str);
str = realloc(str, len + 2);
if (!str)
return NULL; /* ... */
str[len++] = addition;
str[len] = 0;
return str;
}
答案 4 :(得分:0)
char *mystrcat(char *buffer, char addition) {
char *bb;
size_t ll;
ll = buffer ? strlen(buffer) : 0;
bb = realloc(buffer, ll + 2);
if(!bb){
fprintf(stderr, "Memory exhausted in function: mystrcat !\n");
exit(EXIT_FAILURE);
}
buffer = bb; // Safe!!!
buffer[ll] = addition;
buffer[ll+1] = '\0';
return buffer;
}
这样的事情。因此,如果没有记忆,那么在完成申请之前,您根本无法做任何事情。如果只是你的系统没有关闭。
这是一个严重的错误!但你可以看到这条消息。在日志中肯定。如果传递错误的prt缓冲区,则无法保证正常工作。例如,如果您忘记设置null终止符。 strlen发生错误!