2

我尝试重新发明 strcpy C 函数,但是当我尝试运行它时,我得到了这个错误:

Unhandled exception at 0x00411506 in brainf%ck.exe: 0xC0000005: Access violation writing location 0x00415760.

错误发生*dest = *src;在行中。这是代码:

char* strcpy(char* dest, const char* src) {
    char* dest2 = dest;
    while (*src) {
        *dest = *src;
        src++;
        dest++;
    }
    *dest = '\0';
    return dest2;
}

编辑:哇,那很快。这是调用代码(strcpy 在 mystring.c 中定义):

#include "mystring.h"
#include <stdio.h>

int main() {
    char* s = "hello";
    char* t = "abc";
    printf("%s", strcpy(s, t));
    getchar();
    return 0;
}
4

8 回答 8

17
char* s = "hello";
char* t = "abc";
printf("%s", strcpy(s, t));

编译器将目标缓冲区 s 放在只读内存中,因为它是一个常量。

char s[5];
char* t = "abc";
printf("%s", strcpy(s, t));

应该解决这个问题。这会在堆栈上分配目标数组,该数组是可写的。

于 2009-08-13T21:31:25.327 回答
7

明显的潜在问题是您的输出缓冲区没有分配足够的内存,或者您为dest. (可能不是,src否则它会在之前失败。)

请给出一个简短但完整的程序来重现该问题,我们可以检查...

这是一个在 Windows 上对我来说非常有用的例子:

#include <stdlib.h>

char* strcpy(char* dest, const char* src) {
    char* dest2 = dest;
    while (*src) {
        *dest = *src;
        src++;
        dest++;
    }
    *dest = '\0';
    return dest2;
}

void main() {
    char *d = malloc(3);
    strcpy(d, "hello there this is a longish string");
}

请注意,在这种情况下,我必须将实际分配的内存超出相当数量,然后才能使程序死机 - 只是“你好”没有崩溃,尽管它当然可能取决于编译器和执行环境的各个方面。

于 2009-08-13T21:19:02.317 回答
3

你的 strcpy() 很好。您正在写入只读存储器。请在此处查看此说明。

如果你写了这个,你会没事的:

#include "mystring.h"
#include <stdio.h>

int main() {
    char s[] = "hello";
    char t[] = "abc";
    printf("%s", strcpy(s, t));
    getchar();
    return 0;
}
于 2009-08-13T21:31:58.883 回答
1

在主例程中调用重新发明的 strcpy 例程存在问题,两个字符数组: char* s = "hello"; char* t = "abc"; 将在编译时进入内存只读段。当您尝试在例程 strcpy 中写入 s 指向的内存时,并且由于它指向只读段中的一个位置,它将被捕获,并且您将得到一个异常。这些字符串是只读的!

于 2009-08-13T21:38:57.773 回答
0

确保 dest 在调用该函数之前分配了它的内存。

于 2009-08-13T21:19:29.663 回答
0

可能是调用者的问题:你检查了dest指针吗?它是指向有效的东西还是只是垃圾?除此之外,您至少可以检查空指针,例如 if (!dest || !source) { /* 执行某些操作,例如在函数入口处返回 NULL 或抛出异常 */ }。代码看起来不错。不是很安全,但还可以。

于 2009-08-13T21:24:41.850 回答
0

有几个错误。

  1. 您没有分配可以保存复制字符串的返回缓冲区。
  2. 在使用 *src 之前,您不会检查 src 是否为空
  3. 你们都试图在参数中得到答案并返回值。做一个或另一个。
  4. 您可以轻松地超出 dest 缓冲区。

祝你好运。

于 2009-08-13T21:25:11.163 回答
0

当代码开始执行时(通常从主函数开始)。这里的代码表示执行顺序。所以,当进程(执行顺序)开始时,PCB(进程控制块)被创建,pcb具有完整的进程信息,如进程地址空间、内核堆栈、ofdt表等.

在你的代码中

char* s = "你好";
char* t = "abc";

这就是你输入的两个这样的字符串。

在这里,存在于进程地址空间的文本部分中的字符串(表示双引号)。这里文本部分是存在于进程地址空间中的部分之一,文本部分仅具有只读权限。这就是为什么当您尝试修改源字符串/目标字符串时,我们绝不能更改文本集中存在的任何数据。所以,这就是你的代码需要小心的原因。希望你能理解。

于 2014-11-28T15:42:04.687 回答