项目的大致概述:一个嵌入式ARM视频编码器板运行Linux,使用制造商提供的文档不全、支持较差的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 */
};
然后我们有这段代码,简单来说,应该将一个字符串写入IPv4地址:
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,这里将存放tt__IPAddress结构。
DNSInformation->DNSManual->IPv4Address = (char **)soap_malloc(soap, sizeof(char *));
分配一块RAM,指向IPv4Address,其中将写入包含地址的字符串指针。
DNSInformation->DNSManual->IPv4Address[0] = (char *)soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);
现在这段代码有点困扰我,它似乎试图分配内存来保存IPv4Address[0]指向的字符串,但是这看起来可能是一个(32位)指针指向char类型。
这段代码之前可以工作,但在其他地方进行了一些更改后,现在总是在strncpy()处崩溃。
我的问题有两个:
1. 有人能帮我正确理解malloc和指针吗? 2. 如何追踪/调试这个问题?
不幸的是,我们在这个设置中没有GDB设施 - 是的,我确定设置它是可能的,但现在让我们假设由于许多无聊和繁琐的原因而不实际。
目前,在这个小片段的每一行中都散布着调试printf语句,事实上它总是在strncpy()行停止并出现SIGSEGV。
编辑关闭,因为WhozCraig已经找到了答案:
由于某种原因,gSoap已更改结构tt__IPAddress,也许它已经用完了星号,但它以前是什么,它应该是这样的:
struct tt__IPAddress
{
enum tt__IPType Type;
char **IPv4Address; /* note ptr to ptr */
char **IPv6Address;
};
malloc()
的返回值。 - user529758char **
,或者稍后的代码不应该进行sizeof(char)
分配,并且应将该字段视为指向字符串而不是指向指针表的指针。 - Nicholas Wilson