2012-03-27 55 views
2

我的程序/程序异常退出?我怀疑以下代码有问题:如何投射指针(使之变大)

有两个typedef TYPE1,TYPE2。 (TYPE1的尺寸是大于TYPE2)

TYPE1 var1; 
TYPE2 var2; 
.... 
....var2 has been assigned. 
.... 
memset(&var1, 0, sizeof(var1)); 
memcpy(&var1, (TYPE1 *)&var2, sizeof(TYPE1)); 
printf("...."); 
  1. 角色VAR2可能导致访问非法存储器,这可能导致段错误?我认为它可能会混淆内存中var2后面的数据,但不能使分段错误?我发现我的程序在这里退出,因为下面的printf()没有打印任何东西。

  2. 演员将按照存储VAR2即使它是只读(VAR2是刚刚的memcpy源()破坏数据。

  3. 如果我改变它喜欢的memcpy(& VAR1,(TYPE1会发生什么* )& VAR2,的sizeof(TYPE2));

感谢

+1

输出将IT SKIP从'printf'通常被缓冲。在崩溃之前,您的代码可能已经超过了'printf'。您可能想要使用调试器或至少在此发布更多代码。 – Blastfurnace 2012-03-27 07:58:42

+0

你不需要演员。在C中,Casts几乎总是错误的,并且指向需要重构。除此之外,在memcpy()调用中,您试图在对象结束后通过'&var2'访问数据('sizeof var1> sizeof var2')。 – pmg 2012-03-27 08:01:16

+0

@pmg - 我可以限定“C语言中的演员几乎总是错误的吗?”? “将指针指向void指针几乎总是错误的,因为它从来都不是必需的”(要说实话,当将指针指向void *时,我无法想到任何情况*需要在现代C中进行演员表,所以也许我正在wishy-washy),我不想让人想到“...(unsigned int)c”或者“foo((double)i”)在同一个错误类中 – gbulmer 2012-03-27 08:52:47

回答

1

所以首先:当使用memcpy时,不需要投&var2TYPE1*memcpy预计void*,并且可以将任何指针类型转换为void*

这里的问题是,当TYPE1是大于TYPE2和你正在使用sizeof(TYPE1)的大小从var2将数据复制到var1,memcpy的最终将超越var2占用的内存读取。因此,您正在访问您不允许访问的内存。因此,一个分段错误是你可以在那里得到的最好的分段错误,因为这个错误在很长一段时间内也可能没有被注意到,直到它真的可能造成麻烦(未定义行为是关键短语)。

当你只复制sizeof(TYPE2)var2var1字节,你是在内存准入方面OK(只要TYPE1真的大于TYPE2)。

1

威力会导致分段错误,但不是因为您已投入(TYPE1*),而是因为您正在从var2中读取sizeof(TYPE1)。此外,它不会在var2之后破坏数据。事实上,你不需要担心数据损坏。分段故障的目的是为了防止这种非法存储器访问,无论是读取还是写入。

二。不会破坏var2后面的数据。的memcpy原型是

`void * memcpy (void * destination, const void * source, size_t num);` 

观察const。所以它保证source数据不会被修改。此外,强制转换不能决定它是否是无效的内存访问。您尝试复制的字节数,源和目标大小是重要的。

三,正如其他人指出的那样,演员阵容并不重要,在这种情况下,由于您正在从较小的数据结构复制到较大的数据结构,因此不会出现分段错误。

+0

您的意思是会导致分段错误,但不搞乱数据是seg-fault更可取?:)作为旁注转型,而传递给memcpy不会帮助,因为参数总是无效* – keety 2012-03-27 07:58:59

+0

@keety OP似乎担心数据损坏,这就是为什么我提到它没有这样的 事情会发生。无论如何,我编辑我的答案,使我的意图更清晰 – 2012-03-27 08:51:34

+0

是否**:**保证分段错误?或者它是未定义的行为?你的答案似乎很自信地表明分段错误是唯一不可能的结果。 – 2012-03-27 09:00:06

0

我相信这里错过了一个重要的观点。

您不会使指针变大或变短。 int,char,float的所有指针都是相同的大小,并且只包含一个地址(只有当我们在16位DOS时间内有近或远的c指针时,才有这种情况)。指针的大小与机器上的整数大小相同。

所以问题标题是误导性的。但是你会问为什么我们需要类型指针呢?

当我们将指针从发言权TYPE_1 *到TYPE_2 *我们基本上是告诉将是指针指的变量的类型并多少字节,当我们写例如

int * a; 
a++; // skips four bytes if it is a 32 bit integer/machine 

double *b; 
b++; // skips 8 bytes