我似乎已经达到了我的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”。它正确地以null结尾,LARGE_INFO_LENGTH的值很大(比如1024),因此字符串有足够的空间。为安全起见,我从strcpy()更改为strncpy()。
我的背景是较小的嵌入式东西(没有操作系统,没有使用malloc())所以我在说服自己理解这段代码的作用时遇到了一些麻烦。代码是自动生成的/ SDK的一部分,因此它不是我的创建,也没有记录/评论。
以下是我认为它正在做的事情:
DNSInformation->DNSManual = ((struct tt__IPAddress *)soap_malloc(soap, sizeof(struct tt__IPAddress)));
分配一块RAM,由DNSManual指向,其中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- bit)指向char的指针,可能。
此代码以前有效,但是在其他地方进行了一些更改后,它现在是段错误,总是在strncpy()处或在strncpy()期间。
我的问题有两个:
遗憾的是,我们没有这种设置的GDB设施 - 是的我确信它可以设置它,但是现在让我们假设这对于许多蹩脚和乏味的原因是不实际的。
目前我调试printf散布在代码中,事实上在这个小片段的每一行上,它总是在strncpy()行停止使用SIGSEGV。
修改以关闭,因为WhozCraig找到答案:
由于其自身最为人所知的原因,gSoap已经改变了struct tt__IPAddress,也许它已经用完了星号,但它在以前的版本中是什么,它应该是什么,是这样的:
struct tt__IPAddress
{
enum tt__IPType Type;
char **IPv4Address; /* note ptr to ptr */
char **IPv6Address;
};
答案 0 :(得分:2)
代码不遵循结构布局。布局是:
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
是char
指针。但是这个:
DNSInformation->DNSManual->IPv4Address = (char **)soap_malloc(soap, sizeof(char *));
正在为其分配char **
演员。但类型仍然是char *
所以这个:
strncpy(*DNSInformation->DNSManual->IPv4Address, dns_string, LARGE_INFO_LENGTH-1);
取消引用指向单个char
的指针,我可以向您保证,您与平台上的char *
不兼容(可能还有其他任何内容)。
至少应该有关于此编译的警告,如果你的编译器有任何大脑,那么就会出现完全错误。这个看起来就像它本来是这样的:
struct tt__IPAddress
{
enum tt__IPType Type;
char **IPv4Address; /* note ptr to ptr */
char **IPv6Address;
};
用于具有动态指针数组,每个指针是为单个IP地址动态分配的内存。如果它是这样的话,它会更有意义。也就是说,如果您只打算每个结构只有单个 IPv4地址,那么应该更改:
DNSInformation->DNSManual = soap_malloc(soap, sizeof(struct tt__IPAddress)));
if (DNSInformation->DNSManual)
{
DNSInformation->DNSManual->IPv4Address = soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);
if (DNSInformation->DNSManual->IPv4Address)
{
strncpy(DNSInformation->DNSManual->IPv4Address, dns_string, LARGE_INFO_LENGTH-1);
DNSInformation->DNSManual->IPv4Address[LARGE_INFO_LENGTH-1] = 0;
}
}
或类似的东西。
答案 1 :(得分:0)
我觉得它看起来很破碎。
此:
char *IPv4Address; /* optional element of type tt:IPv4Address */
说IPv4Address
是指向字符数据的单个指针,即字符串。
但是它的使用方式如下:
DNSInformation->DNSManual->IPv4Address = (char **)soap_malloc(soap,
sizeof(char *));
这是错的。假设soap_malloc()
(即void *
符合malloc()
)的合理返回值,则不需要演员,但演员与不同实际类型信号出现某种错误。
它将IPv4Address
struct字段视为指针指针,但显然不是。
答案 2 :(得分:0)
我确信它应该与此相似:
DNSInformation->DNSManual = soap_malloc(soap, sizeof(struct tt__IPAddress)));
DNSInformation->DNSManual->IPv4Address = soap_malloc(soap, sizeof(char) * LARGE_INFO_LENGTH);
strncpy(DNSInformation->DNSManual->IPv4Address, dns_string, LARGE_INFO_LENGTH-1);
你的struct包含指向字符串的指针,但首先是分配一个指针数组(char **),然后为这个数组中的第一个指针分配内存。
并且在使用strncpy()之后不要忘记设置二进制零,因为它本身没有设置它。
//编辑:第一部分错了,抱歉
答案 3 :(得分:0)
Here是一个有效的解决方案(我使用malloc
代替soap_malloc
等。)
#include <stdio.h>
#include <stdlib.h>
#define LARGE_INFO_LENGTH 1024
enum tt__IPType { tt__IPv4, tt__IPv6 };
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 */
};
struct tt__DNSInformation
{
struct tt__IPAddress* DNSManual;
};
int main()
{
struct tt__DNSInformation* DNSInformation;
char dns_string[] = "192.168.2.254";
DNSInformation = malloc(sizeof(struct tt__DNSInformation));
DNSInformation->DNSManual = malloc(sizeof(struct tt__IPAddress));
DNSInformation->DNSManual->IPv4Address = malloc(sizeof(char) * LARGE_INFO_LENGTH);
strncpy(DNSInformation->DNSManual->IPv4Address, dns_string, LARGE_INFO_LENGTH - 1);
printf("%s\n", DNSInformation->DNSManual->IPv4Address);
return 0;
}