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

明らかな潜在的な問題は、出力バッファに十分なメモリが割り当てられていないか、 に NULL を渡したことです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");
}

この場合、プログラムを強制終了させる前に、実際に割り当てられたメモリをかなりの量だけ超過する必要があったことに注意してください。「hello」だけではクラッシュしませんでしたが、コンパイラと実行環境のさまざまな側面によっては確かにクラッシュする可能性があります。

于 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ポインターを確認しましたか? それは何か有効なものを指していますか、それとも単にゴミを指していますか? それに加えて、最低限できることは、関数のエントリで if (!dest || !source) { /* NULL を返すか、例外をスローする */ } のように、null ポインターをチェックすることです。コードは問題ないようです。あまり安全ではありませんが、大丈夫です。

于 2009-08-13T21:24:41.850 に答える
0

いくつかのエラーがあります。

  1. コピーされた文字列を保持できるリターン バッファーを割り当てません。
  2. *src を使用する前に src が null かどうかを確認しない
  3. パラメータで答えを取得し、値を返そうとしています。どちらかを行います。
  4. dest バッファは簡単にオーバーランする可能性があります。

幸運を。

于 2009-08-13T21:25:11.163 に答える
0

コードが実行を開始するときはいつでも(通常、メイン関数から開始されます)。ここでコードは実行の順序を意味します。したがって、プロセス(実行の順序)が開始すると、PCB(プロセス制御ブロック)が作成され、プロセスアドレス空間、カーネルスタック、ofdtテーブルなどのプロセスに関する完全な情報を持つpcbがこのようになります.

あなたのコードで

char* s = "こんにちは";
char* t = "abc";

これは、このような 2 つの文字列の入力を取得したものです。

ここでは、プロセス アドレス空間のテキスト セクションに存在する文字列 (二重引用符を意味します)。ここで、テキスト セクションは、プロセス アドレス空間に存在するセクションと、読み取り専用の権限を持つテキスト セクションのみです。そのため、ソース文字列/宛先文字列を変更しようとする場合、テキスト セットに存在するデータを変更することを許可してはなりません。したがって、これがコードの理由であり、注意が必要です。ご理解いただければ幸いです。

于 2014-11-28T15:42:04.687 に答える
0

その関数を呼び出す前に、dest にメモリが割り当てられていることを確認してください。

于 2009-08-13T21:19:29.663 に答える