【问题标题】:why segmentation fault when copying memory为什么复制内存时出现分段错误
【发布时间】:2011-01-21 02:41:11
【问题描述】:

我在 x86_32 上运行 ubuntu...并且在运行此程序时不断出现分段错误。

enter code here
#include<stdio.h>
#include<stddef.h>
char *memcp(char *dest, const char *src, size_t n)
{

    char *dp = dest;
    const char *sp = src;
    while(n--)
        *dp++ = *sp++;
    return dest;

}

int main()
{

    char *s = "abcde";
    char *d;
    char *r = memcp(d,s,6);
    printf("%s",r);

    return(0);
}

这段代码的问题是它运行在我朋友的 x86_64 机器上的 windows 和 ubuntu 上。请帮帮我..

【问题讨论】:

  • @user583878:你正在写一个未初始化的指针,伙计。 *dp++;您是在向随机内存位置写入一些数据吗?有时是SF,有时不是,这取决于它是否通过了当前为程序分配的段! ——阿图尔·穆斯塔芬
  • @user583878:所有未初始化的指针仍然初始化(堆栈分配,如果没有完全优化 - 如果不使用则被淘汰),所以如果我以后以某种方式破坏堆栈状态,(通过调用 dll 导出函数,即),我以后可以以某种有用且有意义的方式使用此指针;)顺便说一下,看看你的代码!你也在做同样的事情,所以我对未初始化指针的错误使用仍然是正确的)))
  • @Artur:这是一个可怕的建议,你应该永远 永远依赖未定义的行为,即使它似乎正在工作。如果你这样做,你将大大降低代码的可移植性和可靠性。当涉及到未定义的行为时,编译器根本不需要保证任何事情。
  • @dreamalax:你知道,我在这里没有给出建议。请告诉我,你为什么认为我在宣传这种可疑的东西?我刚刚说过 可以使用它(不是帖子的作者)的名字,例如在带有 __asm、__emb、__declaspec(noalias)、__declsec(naked) 的 coulpls 中(使用 VC++),所以,我只是不同意你的分类,但我很伤心,使用未初始化的指针是一种不好的做法,而你实际上可以。我没有,所以你应该在使用这样的赞誉时保持礼貌,伙计。实际上,这并不聪明
  • 真的,任何人都可以使用未初始化的指针,... 但只能将其解释为 ponter itsels,而是一个内存位置 如果您没有初始化指针,但是为该指针分配了一些堆栈,为什么不使用这个空间,尽管它在 C/C++ 中被声明为指针,但是 你比其他人更聪明 并将它用作内存位置(不是作为另一个内存位置的参考)?

标签: c segmentation-fault


【解决方案1】:

至少有两种方法可以做到这一点:

malloc方法:

int main(void)
{
    char *s = "abcde";
    char *d = malloc(6);
    char *r = memcp(d, s, 6);
    printf("%s",r);

    free(d);
    return(0);
}

数组方法:

int main(void)
{
    char *s = "abcde";
    char d[6];
    memcp(d, s, 6);

    return 0;
}

请注意,将缓冲区长度硬编码到代码中通常不是一个好主意(例如,您正在硬编码 6)。如果输入的大小发生变化而忘记更新数字 6,就会出现问题。

出现分段错误的原因是指针d 没有指向任何地方。在您的memcp 函数中,您尝试编写此指针,但因为它没有指向任何有意义的程序崩溃的地方。在 C 标准中,这称为未定义的行为,基本上它意味着任何事情都可能发生。

此外,您可能会感兴趣的是,标准 C 库中已经有两个函数可用,memmovememcpy。如果源和目标区域重叠,memmove 很有用。如果您知道它们永远不会重叠,memcpy 可能会更快。

最后我想指出,你不应该接受 Artur 关于未初始化指针使用的建议。您永远不应该依赖未初始化指针的值,这样做意味着您的程序的行为是没有明确定义的。 C 语言规范的附件 J 提到了以下未定义的行为

J.2 未定义行为

  1. 在以下情况下行为未定义:
    • 具有自动存储期限的对象的值在不确定时使用。

【讨论】:

  • 是的,这段代码工作正常,你已经正确解释了行为......非常感谢。
  • @Artur,它不指向任何地方,因为d 没有初始化,这意味着它指向垃圾/随机。垃圾是不可接受的。
  • @Artur Mustafin: “它不指向任何地方” 在这种情况下应该被理解为 “它没有被定义为特别指向任何地方”.
  • @Artur:您正在考虑实施级别。 C 语言规范没有提及数据段和 CPU 级异常,它定义了行为。另外,您误解了我的意思;在实现级别上d 指出没有可靠的实用或有用的地方。就 C 语言规范而言,它只是未定义的行为。
  • @Artur:你对 C 语言规范很熟悉吗? asm 关键字被描述为一个通用扩展,但它不是标准的一部分。另外,我不断添加越来越多的术语,因为您似乎不明白您不使用未初始化的指针。你不能争论这一点,因为即使你认为你已经找到了一些方法来“欺骗”编译器使用未初始化的值,它仍然是 未定义的行为(更不用说是无用的过早优化)。
猜你喜欢
  • 2020-02-27
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
相关资源
最近更新 更多