我有一个给我带来麻烦的C程序。它是X-Plane飞行模拟器的插件。您可以查看整个代码here。基本功能是从卷曲,运行和记录航班信息中提取一些信息,然后最终编制航班报告。
问题是有一个变量行为不端。我在代码的开头声明它,因为它需要跨多个函数。
char fltno[9];
使用插件函数设置内容以从文本框中获取值。它获取FltNoText
窗口小部件的值,长度为8个字符,并将其分配给fltno
变量。
XPGetWidgetDescriptor( FltNoText, fltno, 8);
我使用包含fltno变量的以下方法构建一些消息。
messg = malloc(snprintf(NULL, 0, "Message stuff %s", fltno) + 1);
sprintf(messg, "Message stuff %s", fltno);
这在整个程序运行期间运行良好。直到最后一次需要它为止。这是以:
开头的部分if (inParam1 == (long)SendButton)
这将在最后运行。运行此部分时,fltno
变量不返回任何文本。我以同样的方式使用了许多其他变量,它们似乎都运行良好。我在短途飞行中运行程序并且运行正常,但是我在较长的飞行中运行了两次,该变量在该部分中返回空白。
如果我需要解释更多,请告诉我。你可能会说我没有写过很多C,所以建议得到赞赏。
更多信息
有人建议相邻的decalared变量可能会溢出到fltno
。
Ppass[64]
变量是从Ppass_def
复制的,strcpy(Ppass, Ppass_def);
在代码中设置并且肯定小于64。
tailnum[41]
从插件函数中读取XPLMGetDatab( tailnum_ref, tailnum, 0, 40 );
变量。
fltno
这两个变量都是在程序开头设置的,所以malloc
在最后只有行为不端是没有意义的。
更新1
感谢您的评论。正如rodrigo所建议的那样,我用一些函数调用替换了最长的sprintf
/ fltno
实例。不确定我所做的是你的想法,但它似乎至少与以前一样好。您可以在Github链接上看到新代码。
我还做了更多的测试,并在问题出现的地方缩小了一点。 {11}行最后一次运行时case
变量很好,但是在第1278行的fltno
末尾,它是空白的。我将在稍后尝试进行更多测试,以进一步缩小范围。
更新2
经过更多测试后,我将其缩小到第1292行。在该行之前,strcpy(INlon, dlon);
没问题,之后变为空白。
dlon
if
变量是在switch
声明的char dlon[12];
声明中声明的。
strcpy(dlon, degdm(lon, 1));
每次该部分运行时都会设置此变量,因此在结束之前没有问题是很奇怪的。它是从一个取小数纬度或经度的函数设置的,并返回一个字符串,如" N33 45.9622"。
INlon
char INlon[12];
变量在程序开头声明,这是它唯一设置的时间。
fltno
关于为什么这部分会弄乱strncpy
变量?
更新3
感谢有关sprintf
的建议以及双char INlat[13];
次来电的替代方案。我改变了一些其他的东西,它现在似乎有效,我稍后会做一个完整的测试以确定。
我之前应该抓住的关键部分是纬度/经度字符串只有12个长,这太短了。当经度超过100度时,字符串可以是" W100 22.5678",这是12个字符。这导致结束NULL被切断,并且是我的一些问题的根源。
fltno
当我得到像" W100 22.5678ABC1234"从那些变量,其中" ABC1234"是dlat
变量。
我使用strncpy
指针来避免大小问题,并使用strncpy(INlat, dlat, sizeof(INlat));
确保不会溢出到其他变量。
asprintf
最后,我找到了sprintf
函数来替换char * purl = NULL;
asprintf(&purl, "DATA1=%s&DATA2=%s", DATA1v1, DATA2);
的双实例。我理解这不会适用于所有系统,但它现在只是一个简单的解决方案。
{{1}}
感谢您帮助修复我的代码(假设它现在正在运行)。我觉得我知道足够能够解决它(一旦我指向了正确的方向),但我仍然不确定究竟发生了什么。如果有人想发布一个错误的解释(据你所知),我很乐意接受答案。