我似乎已经达到了我的 Pointer-Fu 的极限,并且正在寻求帮助(或某种脑药)。
该项目的粗略概述:一个运行 Linux 的嵌入式 ARM 视频编码器板,使用制造商提供的文档不完整且支持不充分的 SDK。在其庞大的代码中,有一大堆是由 gSoap 从一些 WSDL 生成的,正是这一点引起了头痛。
在 gSoap 自动生成的巨大数据结构的一部分中,我们有一个地方可以写一些数据(或者,一个地方可以写一个指向我们已经写了一些数据的地方的指针):
struct tt__IPAddress
{
enum tt__IPType Type; /* required element of type tt:IPType */
char *IPv4Address; /* optional element of type tt:IPv4Address */
char *IPv6Address; /* optional element of type tt:IPv6Address */
};
然后我们有这段代码,简而言之,它应该向 IPv4Address 写入一个字符串:
DNSInformation->DNSManual = ((struct tt__IPAddress *)soap_malloc(soap, sizeof(struct tt__IPAddress)));
DNSInformation->DNSManual->IPv4Address = (char **)soap_malloc(soap, sizeof(char *));
DNSInformation->DNSManual->IPv4Address[0] = (char *)soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);
// Code crashes at this next line:
strncpy(*DNSInformation->DNSManual->IPv4Address, dns_string, LARGE_INFO_LENGTH-1);
dns_string 是您所期望的 - 类似于“192.168.2.254”。它正确地以空值结尾,LARGE_INFO_LENGTH 的值很大(例如 1024),因此为字符串提供了足够的空间。为了安全起见,我从 strcpy() 更改为 strncpy()。
我的背景是较小的嵌入式东西(没有操作系统,没有使用 malloc()),所以我很难说服自己理解这段代码在做什么。该代码是自动生成的/SDK 的一部分,所以它不是我的创作,也没有记录/评论。
这就是我认为它正在做的事情:
DNSInformation->DNSManual = ((struct tt__IPAddress *)soap_malloc(soap, sizeof(struct tt__IPAddress)));
正在分配一块由 DNSManual 指向的 RAM,其中 tt__IPAddress 结构将存在。
DNSInformation->DNSManual->IPv4Address = (char **)soap_malloc(soap, sizeof(char *));
正在分配一块由 IPv4Address 指向的 RAM,其中将写入指向包含地址的字符串的指针。
DNSInformation->DNSManual->IPv4Address[0] = (char *)soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);
现在这个让我有点失望,它看起来像是在尝试分配 RAM 来保存 IPv4Address [0] 将指向的字符串,除了在我看来他们正在尝试编写一个(32 位)指针可能是一个字符。
该代码以前可以工作,但是在其他地方进行了一些更改后,它现在总是在 strncpy() 处或期间出现段错误。
我的问题是双重的:
- 有人可以帮助我正确理解 mallocs/pointer-fu 发生了什么吗?
- 有关如何进行跟踪/调试的任何指导?
不幸的是,我们没有使用此设置的 GDB 工具 - 是的,我确信可以设置它,但现在让我们假设由于许多蹩脚和乏味的原因这不切实际。
目前,我已经通过代码大量地调试了 printf,实际上在这个小片段的每一行上,它总是在 strncpy() 行处以 SIGSEGV 停止。
编辑关闭,因为 WhozCraig 已经找到了答案:
出于众所周知的原因,gSoap 更改了 struct tt__IPAddress,也许它已经用完了星号,但它在以前的版本中是什么,应该是什么,是这样的:
struct tt__IPAddress
{
enum tt__IPType Type;
char **IPv4Address; /* note ptr to ptr */
char **IPv6Address;
};