[英]Valgrind invalid write size of 8
I have some code that is suppose to break apart a string that looks like the example below and store it into a data structure. 我有一些代码想将一个字符串分解为下面的示例,并将其存储到数据结构中。
ORGANIZER;CN=John Doe;ON=Another Person;SN=Maybe another
Here is what my function looks like: 这是我的函数:
CalError parseOptionalParam(char * paramString, CalParam * param) {
char * parseString = malloc(strlen(paramString) + sizeof(char*));
strcpy(parseString, paramString);
char * tokenSemi;
tokenSemi = strtok(parseString, ";");
if(tokenSemi == NULL) return SYNTAX;
int i = 0;
while(tokenSemi != NULL) {
tokenSemi = strtok(NULL, ";");
if(tokenSemi == NULL) return SYNTAX;
char * tokenEqual = strtok(tokenSemi, "=");
param->name = malloc(strlen(tokenEqual) + sizeof(char*));
strcpy(param->name, tokenEqual);
param = realloc(param, sizeof(param) + sizeof(char*));
tokenEqual = strtok(tokenSemi, "=");
param->value[i] = malloc(sizeof(char*) + strlen(tokenEqual));
strcpy(param->value[i], tokenEqual);
i++;
}
free(parseString);
return OK;
}
And here is what valgrind is telling me: 这是valgrind告诉我的:
==7925== Invalid write of size 8
==7925== at 0x400E56: parseOptionalParam (calutil.c:79)
==7925== by 0x400CED: parseCalProp (calutil.c:50)
==7925== by 0x400B0B: main (testfile.c:8)
==7925== Address 0x5202508 is 8 bytes after a block of size 16 alloc'd
==7925== at 0x4C2DD9F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7925== by 0x400E13: parseOptionalParam (calutil.c:77)
==7925== by 0x400CED: parseCalProp (calutil.c:50)
==7925== by 0x400B0B: main (testfile.c:8)
The line 79 is the line that starts with param->value[i] =
and then valgrind is referring to the realloc
that is 2 lines above. 第79行是以
param->value[i] =
开头的行,然后valgrind引用的是上面两行的realloc
。 I am confused what is wrong here? 我很困惑这里出了什么问题? Within the
param
structure there is a flexible array member at the end of the structure which is value
. 在
param
结构内,在结构的末尾有一个柔性数组成员,它是value
。 I am simply trying to allocate another array position in the structure and then use that position for a string. 我只是试图在结构中分配另一个数组位置,然后将该位置用于字符串。
At some point in those two lines I am guessing I am doing something incorrect regarding the memory, but I am unsure what it is yet. 在这两行的某个时刻,我猜想我在内存方面做错了什么,但是我不确定它到底是什么。
Within the param structure there is a flexible array member at the end of the structure which is
value
.在param结构内,在结构的末尾有一个柔性数组成员,它是
value
。 I am simply trying to allocate another array position in the structure and then use that position for a string.我只是试图在结构中分配另一个数组位置,然后将该位置用于字符串。
Let's do the math: in order to allocate enough space for CalParam
with its flexible array member that has i
elements you need 让我们做个数学:为了给
CalParam
分配足够的空间,它具有需要i
元素的灵活数组成员
sizeof(CalParam)
- that's the base size of your struct
sizeof(CalParam)
-这是您的struct
的基本大小 (i+1)*sizeof(char*)
- that's an array of char*
of size i+1
(i+1)*sizeof(char*)
-这是大小为i+1
的char*
数组 Therefore, your realloc
call should look like this: 因此,您的
realloc
调用应如下所示:
param = realloc(param, sizeof(*param) + (i+1)*sizeof(char*));
Note the asterisk in front of param
. 注意
param
前面的星号。 This is important, because param
is a pointer. 这很重要,因为
param
是指针。
This is not the end of the story, however, because param
is passed by value, and you are changing its value by realloc
-ing it. 这不是故事的结束,但是,因为
param
是按值传递,并且系统会通过改变其值realloc
-ing它。 This will result in dangling reference in the caller. 这将导致在调用方中悬挂引用。 In order to fix this problem, you need to receive
param
pointer by pointer (ie a double-asterisk pointer), and assign it in your call of realloc
, like this: 为了解决此问题,您需要按指针接收
param
指针(即双星号指针),并在realloc
调用中将其分配,如下所示:
CalError parseOptionalParam(char * paramString, CalParam **param) {
...
*param = realloc(*param, sizeof(**param) + (i+1)*sizeof(char*));
...
}
Note some more asterisks there. 注意那里还有一些星号。 To make your code slightly easier to read, consider replacing the first
sizeof
with sizeof(CalParam)
, like this: 为了使您的代码更易于阅读,请考虑将第一个
sizeof
替换为sizeof(CalParam)
,如下所示:
*param = realloc(*param, sizeof(CalParam) + (i+1)*sizeof(char*));
Finally, you should also fix the potential memory leak with realloc
: instead of assigning to *param
directly, you should assign to a temporary, check for NULL
, and then either assign back to *param
, or free
the old value and report an error. 最后,您还应该使用
realloc
修复潜在的内存泄漏:而不是直接分配给*param
,您应该分配给一个临时变量,检查NULL
,然后分配回*param
,或者free
旧值并报告错误。
I'm assuming the following definition of CalParam
. 我假设以下
CalParam
定义。
typedef struct {
char* name;
char* value[];
} CalParam;
sizeof(param)
is the same as sizeof(typeof(param))
, which is the same as sizeof(CalParam*)
, which is the size of a pointer. sizeof(param)
与sizeof(typeof(param))
相同,与sizeof(CalParam*)
,后者是指针的大小。 You probably meant sizeof(*param)
你可能是说
sizeof(*param)
sizeof(*param)
is the same as sizeof(typeof(*param))
, which is the same as sizeof(CalParam)
. sizeof(*param)
与sizeof(typeof(*param))
相同,与sizeof(CalParam)
相同。 Types are constant, so sizeof
is known at compile-time, so flexible arrays must be ignored in the count. 类型是常量,因此
sizeof
在编译时是已知的,因此必须在计数中忽略灵活的数组。
As such, 因此,
param = realloc(param, sizeof(param) + sizeof(char*));
should be 应该
param = realloc(param, sizeof(CalParam) + sizeof(char*)*(i+1));
Your other memory allocations are wonky too. 您的其他内存分配也很奇怪。 In three places, you have something like
在三个地方,你有类似
char * dst = malloc(strlen(src) + sizeof(char*));
strcpy(dst, src);
That should be 那应该是
char * dst = malloc((strlen(src) + 1) * sizeof(char));
strcpy(dst, src);
But of course, sizeof(char)
is 1
, so we can just use 但是当然,
sizeof(char)
是1
,所以我们可以使用
char * dst = malloc(strlen(src) + 1);
strcpy(dst, src);
But strdup
does the same thing. 但是
strdup
做同样的事情。
char * dst = strdup(src);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.