在下面的例子中,数据没有按预期设置,也没有设置data_handler。
int main() {
char *data;
char *data_handler;
int i = 0;
int len , req;
char test[10] = "test";
for(; i<10; i++){
req = snprintf(NULL, 0 , "[%s] ", test);
printf("%d --> req \n", req);
if (data == NULL) {
data = (char *) malloc ((sizeof(char) * req) + 1);
data_handler = data;
} else {
data_handler = data + len;
data_handler = (char *) malloc ((sizeof(char) * req) +1);
}
len += snprintf(data_handler, sizeof(data) , "[%s] ", test);
printf("\nData --> %s\n", data);
printf("\nData Handler --> %s\n", data_handler);
}
printf ("%s", data);
}
该程序的意图是在字符串中追加10次测试。 (试验指针),但我得到了以下输出。
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
7 --> req
Data --> (��
Data Handler --> [te
(��
Exited: ExitFailure 5
答案 0 :(得分:1)
本地变量不会自动初始化,
char *data;
离开data
未初始化,这意味着它没有存储在其中的值,它是一个随机值,可能被认为是垃圾并且是不可预测的,但它很可能不是NULL
,所以测试是错误的,并且在没有首先初始化它的情况下打印data
。
此外,sizeof
运算符返回类型的大小而不是分配的大小。您应该保留分配的大小,以便以后使用它。 sizeof
运算符也为您提供了数组的大小,但data
不是数组,而是指针。
最后:
malloc()
的返回值。 Read here for more about it。sizeof(char)
,因为根据定义,它是=== 1
。答案 1 :(得分:1)
除了讨论的其他问题之外,您的代码还会严重泄漏内存。您不能简单地每次迭代继续malloc
data_handler
。执行此操作时,将覆盖先前分配的块的地址,从而失去free
先前分配的内存的能力。相反,您必须realloc
原始内存块,保留指向内存块起始地址的指针data
,然后相应地更新data_handler
。
这是一个基本的内存管理问题。
相反,您似乎尝试执行以下操作。如果我误解了你的目标,我会道歉,否则你的代码没有意义:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *data = NULL;
char *data_handler = NULL;
int i = 0, len = 0, req = 0;
char test[10] = "test";
req = snprintf (NULL, 0, "[%s] ", test);
printf ("%d --> req\n", req);
for (; i < 10; i++) {
if (data == NULL) {
data = malloc (req + 1);
data_handler = data;
}
else {
char *tmp = realloc (data, len + req + 1); /* realloc data */
if (!tmp) { /* validate */
fprintf (stderr, "realloc() error: virtual memory exhausted.\n");
return 1;
}
data = tmp; /* assign tmp to data */
data_handler = data + len; /* update data_handler */
}
len += snprintf (data_handler, sizeof test, "[%s] ", test);
printf ("-- (len: %d)\nData --> %s\n", len, data);
printf ("Data Handler --> %s\n", data_handler);
}
putchar ('\n');
free (data);
return 0;
}
示例使用/输出
$ ./bin/snprintfnoinit
7 --> req
-- (len: 7)
Data --> [test]
Data Handler --> [test]
-- (len: 14)
Data --> [test] [test]
Data Handler --> [test]
-- (len: 21)
Data --> [test] [test] [test]
Data Handler --> [test]
-- (len: 28)
Data --> [test] [test] [test] [test]
Data Handler --> [test]
-- (len: 35)
Data --> [test] [test] [test] [test] [test]
Data Handler --> [test]
-- (len: 42)
Data --> [test] [test] [test] [test] [test] [test]
Data Handler --> [test]
-- (len: 49)
Data --> [test] [test] [test] [test] [test] [test] [test]
Data Handler --> [test]
-- (len: 56)
Data --> [test] [test] [test] [test] [test] [test] [test] [test]
Data Handler --> [test]
-- (len: 63)
Data --> [test] [test] [test] [test] [test] [test] [test] [test] [test]
Data Handler --> [test]
-- (len: 70)
Data --> [test] [test] [test] [test] [test] [test] [test] [test] [test] [test]
Data Handler --> [test]
内存使用/错误检查
在任何动态分配内存的代码中,对于分配的任何内存块,您都有2个职责:(1)始终保留指向起始地址的指针内存块,(2)当不再需要时,它可以释放。
必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已释放所有内存你分配的记忆。对于Linux valgrind
是正常的选择。它使用简单。
$ valgrind ./bin/snprintfnoinit
==25279== Memcheck, a memory error detector
==25279== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25279== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==25279== Command: ./bin/snprintfnoinit
==25279==
7 --> req
-- (len: 7)
Data --> [test]
Data Handler --> [test]
-- (len: 14)
...
==25279==
==25279== HEAP SUMMARY:
==25279== in use at exit: 0 bytes in 0 blocks
==25279== total heap usage: 10 allocs, 10 frees, 395 bytes allocated
==25279==
==25279== All heap blocks were freed -- no leaks are possible
==25279==
==25279== For counts of detected and suppressed errors, rerun with: -v
==25279== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
始终确认释放所有堆块 - 不可能泄漏并且同样重要错误摘要:0个上下文中的0个错误。
查看代码的更改,如果您有任何问题,请告诉我。
答案 2 :(得分:0)
将这个include添加到代码中以使其编译:
#include <stdio.h>
编译器提供有关代码未按预期工作的原因的提示:
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
test.c
d:\temp\test.c(16) : warning C4700: uninitialized local variable 'data' used
d:\temp\test.c(24) : warning C4700: uninitialized local variable 'len' used
修改强>
下面是你的代码添加了一个包含文件,以便编译并通过编译器建议的启动变量来修复警告:
#include <stdio.h>
int main() {
char *data=0;
char *data_handler;
int i = 0;
int len=0, req;
char test[10] = "test";
for(; i<10; i++){
req = snprintf(NULL, 0 , "[%s] ", test);
printf("%d --> req \n", req);
if (data == NULL) {
data = (char *) malloc ((sizeof(char) * req) + 1);
data_handler = data;
} else {
data_handler = data + len;
data_handler = (char *) malloc ((sizeof(char) * req) +1);
}
len += snprintf(data_handler, sizeof(data) , "[%s] ", test);
printf("\nData --> %s\n", data);
printf("\nData Handler --> %s\n", data_handler);
}
printf ("%s", data);
}
以下是该代码产生的输出:
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
7 --> req
Data --> [te
Data Handler --> [te
[te