我的代码工作正常,但我收到 valgrind 错误。我想知道如何更正我的代码以正确使用这些 malloc 和 free 语句与 char * * dest。请不要告诉我不要 malloc 和 free,除非我在不正确的位置这样做。非常感谢在 answer03.c 中为 strcat_ex 提供一个或两个更正代码,或者解释我对 malloc、free 和 malloc 之后的初始化的误解。我为这篇长篇文章提前道歉,但我想提供一切必要的东西。
更多信息:我主要关注方法 strcat_ex (这与 strncat 不同——阅读函数描述以查看与 int *n 的区别)。问题的出现是因为我需要重新分配 dest (char **) 中字符串 (char *) 的参数内存,并且如果它没有分配足够的空间,并且在我 malloc 之后它没有被初始化。这对我来说没有意义如何在 malloc 之后初始化“堆”内存。我不相信初始化必须在 malloc 之后发生。
注意:pa03.c 和 answer03.h 根本不应该改变。
这是相关的 valgrind 错误(memcheck.log):
==28717== 1 errors in context 7 of 10:
==28717== Conditional jump or move depends on uninitialised value(s)
==28717== at 0x402D09C: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==28717== by 0x8048F98: strcat_ex (answer03.c:29)
==28717== by 0x8048631: main (pa03.c:16)
==28717== Uninitialised value was created by a heap allocation
==28717== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==28717== by 0x8048F46: strcat_ex (answer03.c:21)
==28717== by 0x8048631: main (pa03.c:16)
==28717==
==28717== ERROR SUMMARY: 10 errors from 10 contexts (suppressed: 0 from 0)
引用的行:
第 16 行(来自pa03.c)不应更改。作为调用方法参数def、n、src和返回变量 result 的示例,在pa03.c中声明如下:
result=strcat_ex(&dest, &n, src);
第 21 行(来自answer03.c):
char * buffer = malloc(1 + 2 * (sizeOfDest + strlen(src)));
第 29 行(来自answer03.c):
buffer = strcat(buffer,src);
这是相关的源代码。这是 valgrind 错误所在并且需要 stackoverflow 知识(answer03.c):
编辑:已添加注释并已注释掉行以删除我在代码中与我的问题没有直接关系的错误。对于这些令人发指的错误,我深表歉意,但在其中留下了线条以帮助未来的读者理解。
#include "answer03.h"
#include <string.h>
char * strcat_ex(char * * dest, int * n, const char * src)
{
//Edit: Removed Line Below - Irrelevant variable resplaced with *n
//int sizeOfDest;
if(*dest == NULL)
{
*n = 0;
}
else
{
//Edit: Removed Line Below - variable replaced with *n
//sizeOfDest = strlen(*dest);
}
//Edit: Removed Line Below
//if(*dest != NULL && sizeOfDest >= 1 + sizeOfDest + strlen(src))
//Edit: Corrected Line
if(*dest !=NULL && *n >= 1 + strlen(*dest) + strlen(src))
{
strcat(*dest, src);
}
else
{
//Edit: *n replaced sizeOfDest and changes needed to be made to reflect this. Commented out lines were incorrect and irrelevant. Lines directly below them are the corrected versions, until you reach the next blank line
//*n = 1 + 2 * (sizeOfDest + strlen(src));
if(*dest != NULL)
*n = 1 + 2 * (strlen(*dest) + strlen(src));
else
*n = 1 + 2 * strlen(src);
//char * buffer = malloc(1 + 2 * (sizeOfDest + strlen(src)));
char * buffer = malloc(sizeof(char) * *n);
if(*dest != NULL)
{
strcpy(buffer, *dest);
free(*dest);
}
*dest = malloc(sizeof(buffer));
buffer = strcat(buffer,src);
*dest = buffer;
}
return *dest;
}
低于此点的所有内容都应保持不变并且已知是正确的:
我的编译语句(Makefile):
gcc -Wall -Wshadow -g pa03.c answer03.c -o pa03
我的 valgrind 声明(Makefile):
valgrind --tool=memcheck --leak-check=full --verbose --track-origins=yes --log-file=memcheck.log ./pa03
这是 strcat_ex ( answer03.h ) 的函数定义:
#ifndef PA03_H
#define PA03_H
#include <stdlib.h>
/**
* Append the C-string 'src' to the end of the C-string '*dest'.
*
* strcat_ex(...) will append the C-string 'src' to the end of the string
* at '*dest'. The parameter 'n' is the address of a int that specifies how
* many characters can safely be stored in '*dest'.
*
* If '*dest' is NULL, or if '*dest' is not large enough to contain the result
* (that is, the sum of the lengths of *dest, src, and the null byte), then
* strcat_ex will:
* (1) malloc a new buffer of size 1 + 2 * (strlen(*dest) + strlen(src))
* (2) set '*n' to the size of the new buffer
* (3) copy '*dest' into the beginning of the new buffer
* (4) free the memory '*dest', and then set '*dest' to point to the new buffer
* (5) concatenate 'src' onto the end of '*dest'.
*
* Always returns *dest.
*
* Why do we need to pass dest as char * *, and n as int *?
* Please see the FAQ for an answer.
*
* Hint: These <string.h> functions will help: strcat, strcpy, strlen.
* Hint: Leak no memory.
*/
char * strcat_ex(char * * dest, int * n, const char * src);
//...
以下是调用 source 作为测试的相关代码(pa03.c):
#include <stdio.h>
#include <string.h>
#include "answer03.h"
int main(int argc, char **argv)
{
char * src;
char * dest;
char * result;
int n;
src="World!";
dest=NULL;
result=strcat_ex(&dest, &n, src);
printf("src=\"World!\";\ndest=NULL;\nstrcat_ex(&dest, &n, src);\n --> gives %s with n=%d\n",result,n);
result=strcat_ex(&dest, &n, "");
printf("Then strcat_ex(&dest, &n, \"\") yields --> gives %s with n=%d\n",result,n);
strcpy(dest,"abc");
result=strcat_ex(&dest, &n, "def");
printf("Then strcpy(dest,\"abc\"); strcat_ex(&dest, &n, \"def\") yields --> gives %s with n=%d\n",result,n);
free(dest);
//...
这是相关的输出(来自pa03.c的打印语句):注意这是正确的输出(我当前的代码能够产生)。
src="World!";
dest=NULL;
strcat_ex(&dest, &n, src);
--> gives World! with n=13
Then strcat_ex(&dest, &n, "") yields --> gives World! with n=13
Then strcpy(dest,"abc"); strcat_ex(&dest, &n, "def") yields --> gives abcdef with n=13
//...
最后的话:
我附上了编译此代码所需的文件以及使用 gcc 和 valgrind 在 linux 中的 valgrind 错误日志。valgrind 中还有更多内容,但我发布了我认为最相关的内容。提前致谢。
Zip 包括所有文件:
http ://www.filedropper.com/files_11