【发布时间】:2013-03-25 01:03:15
【问题描述】:
我又有一个关于 C 的工作原理的问题。(由 VS2012 编译的 ANSI-C)
我正在将独立程序 (.exe) 重构为 .dll。到目前为止,这工作得很好,但是在记录日志时我偶然发现了一些问题。让我解释一下:
原始程序 - 在运行时 - 写入日志文件并将信息打印到屏幕上。由于我的 dll 将在网络服务器上运行,许多人同时访问有
- 没有真正的机会正确处理日志文件(并在它们之后进行清理)
- 没有任何人会看到的控制台窗口
所以我的目标是将要放入日志文件或屏幕上的所有内容写入类似字符串的变量(我知道 C 中没有字符串),然后我可以稍后将 requet 传递给调用者(也是一个 dll,但用 C# 编写)。
因为在 C 中这样的事情是不可能的:
char z88rlog;
z88rlog="First log-entry\n";
z88rlog+="Second log-entry\n";
我有两种可能:
char z88rlog[REALLY_HUGE];- 动态分配内存
在我看来,第一种方法是被忽略,因为:
- 内存的潜在浪费是相当巨大的
- 我可能仍然需要比
REALLY_HUGE更多的内存,从而造成缓冲区溢出
这让我有了第二种方式。我已经为此做了一些工作,并提出了两个解决方案,其中任何一个都无法正常工作。
/* Solution 1 */
void logpr(char* tmpstr)
{
extern char *z88rlog;
if (z88rlog==NULL)
{
z88rlog=malloc(strlen(tmpstr)+1);
strcpy(z88rlog,tmpstr);
}
else
{
z88rlog=realloc(z88rlog,strlen(z88rlog)+strlen(tmpstr));
z88rlog=strcat(z88rlog,tmpstr);
}
}
在解决方案 1 中(等于解决方案 2,您会发现)我通过 char tmpstr[255]; 传递我的新日志条目。我的“日志文件”z88rlog 是全局声明的,所以我需要extern 才能访问它。然后我检查是否为z88rlog 分配了内存。如果没有,我会分配我的日志条目大小的内存(我的\0 +1)并将tmpstr 的内容复制到z88rlog。如果是,我会为z88rlog 重新分配内存,其大小为原来的大小+tmpstr 的长度(+1)。然后使用strcat 连接两个“字符串”。使用断点和直接窗口我获得了以下输出:
z88rlog
0x00000000 <Schlechtes Ptr>
z88rlog
0x0059ef80 "start Z88R version 14OS"
z88rlog
0x0059ef80 "start Z88R version 14OS
opening file Z88.DYNÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««þîþîþîþ"
显示连续三个logpr调用(断点在strcpy/strcat之前)。最后无法区分的乱码是由于内存分配造成的。之后 VS 发出一条错误消息,指出某些原因导致调试器在realloc.c 中设置断点。因为这显然行不通,所以我炮制了我的绝妙解决方案 2:
/* Solution 2 */
void logpr(char* tmpstr)
{
extern char *z88rlog;
char *z88rlogtmp;
if (z88rlog==NULL)
{
z88rlog=malloc(strlen(tmpstr)+1);
strcpy(z88rlog,tmpstr);
}
else
{
z88rlogtmp=malloc(strlen(z88rlog)+strlen(tmpstr+1));
z88rlogtmp=strcat(z88rlog,tmpstr);
free(z88rlog);
z88rlog=malloc(strlen(z88rlogtmp)+1);
memcpy(z88rlog,z88rlogtmp,strlen(z88rlogtmp)+1);
free(z88rlogtmp);
}
}
这里我的目标是创建我的日志文件的副本,释放原件的内存为新大小的原件创建新内存并将内容复制回来。并且不要忘记释放临时副本,因为它是通过 malloc 分配的。当它到达free 时会立即崩溃,再次告诉我堆可能已损坏。
所以让我们暂时免费评论。这确实工作得更好 - 让我松了一口气 - 但是在构建日志字符串时突然不是所有来自 z88rlogtmp 的字符都被复制了。但一切仍然正常工作。直到突然我再次被告知堆可能被破坏并且调试器在_heap_alloc (size_t size)in malloc.csize的末尾放置了一个断点 - 根据调试器 - 值为 1041。
所以我有 2 种(或 3 种)方法想要实现这种“字符串增长”,但没有一种有效。给我大小的错误可能会让我得出数组已经变大的结论吗?我希望我能很好地解释我想做什么,有人可以帮助我:-) 提前致谢!
讽刺也许我应该去买一些新的电脑堆。它适合 RAM 插槽吗?谁能推荐一个好品牌? 讽刺
【问题讨论】:
标签: c char malloc heap-memory realloc