我可能错过了一些明显的东西,但我的C很生疏,我没有任何运气能够理解这一点。我有一个循环,我想迭代来自libdvdnav的uint64_t
值数组,然后格式化值并将它们插入到字符串中。
libdvdnav的标题定义了我正在调用的函数:
uint32_t dvdnav_describe_title_chapters(dvdnav_t *self, int32_t title, uint64_t **times, uint64_t *duration);
以下是我如何定义所使用的变量并执行调用(dvdnav
和args[0]
在其他地方定义和初始化):
uint64_t *times;
uint64_t duration;
uint32_t times_array_len;
times_array_len = dvdnav_describe_title_chapters(dvdnav, atoi(args[0]), ×, &duration);
下面的代码似乎有效,并编译&运行没有错误,但当然只插入数组中的第一个值:
int i = 0;
uint64_t a_time = times[0];
while(i < times_array_len){
char time_json[100];
sprintf(time_json, "{\"chapter\":\"%d\",\"time\":\"%u\"},", i, a_time);
strcat(payload, time_json);
i++;
}
如果我修改它以选择数组中的每个值,它仍然编译干净,但在运行时抛出一个段错误:
int i = 0;
while(i < times_array_len){
char time_json[100];
sprintf(time_json, "{\"chapter\":\"%d\",\"time\":\"%u\"},", i, times[i]);
strcat(payload, time_json);
i++;
}
我想也许其中一个数组元素中存在一些问题(一个太大的值,意外,NULL等),但即使我用已知合理的变量替换变量i
元素(比如,0
)它仍然是段错误。
我确定在这里可以做出无数其他改进(更安全的分配,溢出保护等),但我努力破译的部分是从数组中获取这些值进入我的格式化字符串。
答案 0 :(得分:1)
payload
如何定义?如果它太短而不能包含字符串那么你就会崩溃。
您可以通过以下几种方式解决这个问题:
1)由于您现在的json条目数将为times_array_len
,您可以使用大小为100 * malloc
的{{1}}在堆上分配字符串 - 您永远不会超过该值(再次,不确定是否使用固定长度的json缓冲区是聪明的,然后strcat应该是安全的。您甚至可以直接对times_array_len
缓冲区进行直接sprintf
调用,因为您现在可以通过跟踪payload
的返回值来确定偏移量。像这样:
sprintf
2)为了避免在单个条目上超过100个字符长度,您可以明智地分配#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv)
{
__int64 pTimes[] = { 1, 2, 3 ,4};
size_t nTimeCount = sizeof(pTimes) / sizeof(pTimes[0]);
size_t nPayloadOffset = 0;
char* pPayload = (char*)malloc(100 * nTimeCount);
if (pPayload)
{
for (size_t nTimeIndex = 0; nTimeIndex < nTimeCount; ++nTimeIndex)
{
nPayloadOffset += sprintf(&pPayload[nPayloadOffset], "{\"chapter\":\"%d\",\"time\":\"%u\"},", nTimeIndex, pTimes[nTimeIndex]);
}
printf("%s\n", pPayload);
free(pPayload);
}
return EXIT_SUCCESS;
}
初始大小,然后计算每个条目的大小并重新分配pPlayoad
如果它变得太短了
3)如果C ++是一个选项,请使用C ++和pPayload
:
std::stringstream