我有以下代码,我需要格式化输出。但是当我这样做时,一个内存异常导致无效的内存访问异常。我在这做错了什么?请指教。
char* strData = malloc(tag_operation_report->tag.epc.size / 2),
char* strTemp= malloc(tag_operation_report->tag.epc.size / 2);
do
{
for (int i = 0; i < tag_operation_report->tag.epc.size / 2; i++)
{
uint32_t num = tag_operation_report->tag.epc.bytes[i];
strTemp=sprintf(L"%x ", num);
strData+=strTemp;
}
} while (tag_operation_report->tag.epc.size != 0);
data = (void *)strData;
free(strTemp);
free(strData);
以下所示为例外。
Unhandled exception at 0x00007FF83C3C3A5D (msvcr120d.dll) in RFIDTest.exe: 0xC0000005: Access violation reading location 0x00000000000000E2.
答案 0 :(得分:4)
问题1
strTemp=sprintf(L"%x ", num);
您要将int
分配给strTemp
,即char*
。我很惊讶你的编译器没有警告你。目前尚不清楚你的目标是什么。
问题2
strData+=strTemp;
再次,您的编译器应该告诉您这是一个错误。您无法将char*
增加另一个char*
。
问题3
free(strTemp);
free(strData);
您正在调用与free
返回的值不同的指针值malloc
。这会导致未定义的行为。
建议的解决方案
也许这就是你打算做的事情:
// Don't need to use dynamic memory allocation for this.
// It's only going to be used in sprintf. 20 characters should
// be large enough for that.
char strTemp[20];
// Bootstrap strData.
int strDataSize = 0;
char* strData = malloc(1);
// If memory allocation failed, deal with the problem
if ( strData == NULL )
{
exit(EXIT_FAILURE);
}
strData[0] = '\0';
for (int i = 0; i < tag_operation_report->tag.epc.size / 2; i++)
{
uint32_t num = tag_operation_report->tag.epc.bytes[i];
sprintf(strTemp, "%x ", num);
// Increase the size of strData
strDataSize += strlen(strTemp);
// Allocate more memory for strData.
strData = realloc(strData, strDataSize + 1);
// If memory allocation failed, deal with the problem
if ( strData == NULL )
{
exit(EXIT_FAILURE);
}
// Add strTemp to strData.
strcat(strData, strTemp);
}
data = (void *)strData;
// Don't free strData. If you do, data will be dangling pointer.
// free(strData);
答案 1 :(得分:3)
这是一个错误:sprintf(L"%x ", num);
sprintf
的第一个参数是一个分配的缓冲区,输出将放入该缓冲区。第二个参数是格式字符串。
因此,您尝试覆盖字符串文字L"%x"
,并且num
也不是有效的格式字符串。你的编译器应该警告你这个错误 - 注意编译器的输出。
执行strTemp =
也是一个错误,strTemp += strData
也是如此。你不能添加指针,编译器也应该对此发出警告。
另一个错误是data = (void *)strData; free(strData);
,这使得data
指向释放的内存。
如果你试图连接字符串,那么你将完全以错误的方式处理它。您需要了解指针不是字符串。指针指向指向可能包含字符串的内存区域。您必须考虑已分配的内存块以及指针指向的位置。
答案 2 :(得分:1)
sprintf只修改已分配的内存。您必须将目标缓冲区指针作为第一个参数传递。 http://man7.org/linux/man-pages/man3/sprintf.3.html
如果您不是100%确定输出适合您的缓冲区,最好使用snprintf再接受一个参数来判断缓冲区中剩余的空间。这可以防止sprintf写入错误导致的错误。