私のコードは正常に動作しますが、valgrind エラーが発生します。これらの malloc および free ステートメントを char * * dest で正しく使用することに関して、コードを修正する方法を知りたいです。間違った場所で実行していない限り、malloc と free を実行しないように言わないでください。answer03.c の strcat_ex の修正されたコード、または malloc 後の malloc、free、および初期化に関する私の誤解の説明のいずれかまたは両方を提供していただければ幸いです。長い投稿を前もってお詫びしますが、必要なものはすべて提供したかったのです。
詳細情報: 私は主にメソッド strcat_ex に焦点を当てています (これは strncat と同じではありません。関数の説明を読んで int *n との違いを確認してください)。この問題は、文字列 (char *) のパラメーター メモリを dest (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