我有功能:
char *zap(char *ar) {
char pie[100] = "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '";
char dru[] = "' )";
strcat(pie, ar);
strcat(pie, dru);
return pie;
}
主要有:
printf("%s", zap( argv[1] ) );
编译时我收到警告:
test.c: In function ‘zap’:
test.c:17: warning: function returns address of local variable
我该如何归还char *?
答案 0 :(得分:18)
你最好的选择可能就是不要将它返回 - 而是将你想要填充的缓冲区作为参数传递给函数。
void zap(char * pie, const char *ar) {
strcpy( pie, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '");
char dru[] = "' )";
strcat(pie, ar);
strcat(pie, dru);
}
然后这样称呼:
char pie[100];
zap( pie, "foo" );
要对此函数进行防范,您还需要传入缓冲区的长度,然后在每次要添加新查询元素时对其进行检查。
答案 1 :(得分:12)
发布的解决方案一切正常,但只是回答您的问题,为什么会收到警告:
当您在函数中将pie声明为缓冲区时,您没有分配堆内存,而是在堆栈中创建变量。该内存内容仅在该函数的范围内得到保证。一旦你离开函数(返回之后),该内存可以被重用,你可以找到你指向的内存地址随时被覆盖。因此,您将收到警告,您正在返回一个指向内存的指针,该指针无法保证可以保留。
如果要在可以在该函数外引用的c函数中分配持久性内存,则需要使用malloc(或其他类型的堆内存分配函数)。这将在堆上为该变量分配内存,并且它将持久直到使用free函数释放内存。如果你不清楚堆栈和堆内存,你可能想要谷歌,它会让你的C体验更顺畅。
答案 2 :(得分:4)
使用pie
malloc
分配内存
答案 3 :(得分:4)
#include <assert.h> #include <stdio.h> /** * Returns the buffer, just for convenience. */ char *generateSQL(char *buf, size_t bufsize, const char *ar) { int n; n = snprintf(buf, bufsize, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '%s')", ar); /* FIXME: Properly escape the argument, just in case it contains an apostrophe. */ assert(0 <= n && (unsigned) n < bufsize); return buf; } int main(int argc, char **argv) { char buffer[4096]; assert(1 < argc); printf("%s\n", generateSQL(buffer, sizeof(buffer), argv[1])); return 0; }
答案 4 :(得分:2)
char pie[100];
void zap(char* pie, char *ar) {
char pies[100] = "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '";
char dru[] = "' )";
strcpy(pie, pies);
strcat(pie, ar);
strcat(pie, dru);
}
zap(pie, argv[1]);
printf("%s", pie );
答案 5 :(得分:2)
我强烈建议更改此功能,让用户传递缓冲区和长度,然后使用该缓冲区。或者,您可以分配返回值的新实例,即malloc
,但请务必向用户发表评论以便再次释放。
答案 6 :(得分:1)
声明你的char数组静态
static char pie[100] = "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '";
答案 7 :(得分:0)
略有不同的方法:
void zap(char **stmt, char *argument, size_t *stmtBufLen)
{
char *fmt="INSERT INTO test(nazwa, liczba) VALUES ('nowy wpis', '%s')";
/**
* Is our current buffer size (stmtBufLen) big enough to hold the result string?
*/
size_t newStmtLen = strlen(fmt) + strlen(argument) - 2;
if (*stmtBufLen < newStmtLen)
{
/**
* No. Extend the buffer to accomodate the new statement length.
*/
char *tmp = realloc(*stmt, newStmtLen + 1);
if (tmp)
{
*stmt = tmp;
*stmtLen = newStmtLen+1;
}
else
{
/**
* For now, just write an error message to stderr; the statement
* buffer and statement length are left unchanged.
*/
fprintf(stderr, "realloc failed; stmt was not modified\n");
return;
}
}
/**
* Write statement with argument to buffer.
*/
sprintf(*stmt, fmt, argument);
}
int main(void)
{
char *stmtBuffer = NULL;
size_t stmtBufferLen = 0;
...
zap(&stmtBuffer, "foo", &stmtBufferLen);
...
zap(&stmtBuffer, "blurga", &stmtBufferLen);
...
zap(&stmtBuffer, "AReallyLongArgumentName", &stmtBufferLen);
...
zap(&stmtBuffer, "AnEvenLongerRidiculouslyLongArgumentName", &stmtBufferLen);
...
free(stmtBuffer);
return 0;
}
此版本使用动态内存分配来根据需要调整缓冲区大小,从NULL缓冲区指针开始(realloc(NULL,size)== malloc(size))。这样您就不必担心开始使用“足够大”的缓冲区。唯一的缺点是你需要记住在你完成缓冲区时释放缓冲区(我通常不喜欢在这样的调用者和被调用者之间分配内存管理职责;如果我考虑它超过10分钟,我' d想出更好的东西)。
答案 8 :(得分:0)
我进行此类操作的方法是使本地缓冲区成为特定于线程的静态变量:
const int max_pie_cnt = 100;
const char *zap(char *ar) {
static __declspec(thread) char pie[max_pie_cnt]; // use TLS to store buffer
strcpy(pie, "INSERT INTO test (nazwa, liczba) VALUES ('nowy wpis', '");
char dru[] = "' )";
strcat(pie, ar);
strcat(pie, dru);
return pie;
}
我对专家的评论非常好奇。
不过,让我们暂时忘记缓冲区溢出问题。