简体   繁体   English

无法在 CLION IDE 中使用 gdb 访问地址 memory。如何设置 gdb?

[英]Cannot access memory at address using gdb in CLION IDE. How do I setup gdb?

I get the error "Cannot access memory at address 0x100403055" when I try and set a memory value to 0x00 when stopped in the debugger.当我尝试在调试器中停止时将 memory 值设置为 0x00 时,出现错误“无法在地址 0x100403055 访问 memory”。

Is there a special switch I need to set to enable the set operation?是否需要设置特殊开关才能启用设置操作?

Here is my complete C code file "main.c"这是我完整的 C 代码文件“main.c”

#include <stdio.h>
#include <string.h>
/*
  separator - consume all non-token characters until next token.  This includes:
    comments:   '#' 
    nesting:    '{'
    unnesting:  '}'
    whitespace: ' ','\t','\n'

    *nest is changed according to nesting/unnesting processed
 */
static void separator(int *nest, char **tokens) {
    char c, *s;

    s = *tokens;
    while ((c = *s)) {
        /* #->eol = comment */
        if (c == '#') {
            s++;
            while ((c = *s)) {
                s++;
                if (c == '\n')
                    break;
            }
            continue;
        }
        if (c == '{') {
            (*nest)++;
            s++;
            continue;
        }
        if (c == '}') {
            (*nest)--;
            s++;
            continue;
        }
        if (c == ' ' || c == '\n' || c == '\t') {
            s++;
            continue;
        }
        break;
    }
    *tokens = s;
}

/*
  token - capture all characters until next separator, then consume separator,
    return captured token, leave **tokens pointing to next token.
 */
static char *token(int *nest, char **tokens) {
    char c, *s, *t;
    char terminator = '\0';
    s = t = *tokens;
    while ((c = *s)) {
        if (c == '#'
            || c == ' ' || c == '\t' || c == '\n' || c == '{' || c == '}')
            break;
        s++;
    }
    *tokens = s;
    separator(nest, tokens);
    /* Breakpoint here to examine and manipulate memory */
    *s = '\0';
    return t;
}


struct test_case {
    char *input;
    int nest;
    char *expected_output;
};


int main() {
    int nest = 0;
    int TESTSEP = 0;
    if (TESTSEP>0) {
        char *tokens = "# this is a comment\n{nesting {example} unnesting}\n  \t end";

        separator(&nest, &tokens);

        printf("nest: %d\n", nest);
        printf("tokens: %s\n", tokens);

        return 0;
    } else {
        struct test_case test_cases[] = {
                {"hello world",  0, "hello"},
                {"hello#world",  0, "hello"},
                {"hello{world}", 0, "hello"},
                {"hello  world", 0, "hello"},
                {"hello\tworld", 0, "hello"},
                {"hello\nworld", 0, "hello"},
        };

        for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
            struct test_case test_case = test_cases[i];
            char *tokens = test_case.input;
            char *output = token(&test_case.nest, &tokens);
            if (strcmp(output, test_case.expected_output) != 0) {
                printf("Test case %d failed: expected %s, got %s\n", i, test_case.expected_output, output);
            }
        }

        return 0;
    }
}

In the token function there is a comment line where I place a breakpoint and drop into the gdb debugger.token function 中有一个注释行,我在其中放置一个断点并放入 gdb 调试器。 The code is supposed to write a '\0' at the address of the pointer *s to truncate the string.该代码应该在指针 *s 的地址处写入一个 '\0' 以截断字符串。

When I'm in the debugger and I examine the 's' variable I get the following:当我在调试器中检查“s”变量时,我得到以下信息:

  (gdb) x s
  0x100403055:  0x726f7720

When I try and set the variable I get:当我尝试设置变量时,我得到:

(gdb) [![set *0x0000000100403055 = 0x726f7700][1]][1]
Cannot access memory at address 0x100403055

I'm using the CLION IDE and am a novice.我正在使用 CLION IDE 并且是新手。 I'm not sure if its an IDE problem, a user problem or some external memory protection mechanism that is preventing this.我不确定它是 IDE 问题、用户问题还是某些阻止此问题的外部 memory 保护机制。 Does anyone know how to make this work?有谁知道如何使这项工作?

Here is a screenshot of the IDE:这是 IDE 的屏幕截图: IDE在断点处停止的截图

When I run the code (without the debugger) I get this output:当我运行代码(没有调试器)时,我得到这个 output:

./explore.exe 

Test case 0 failed: expected hello, got hello world 
Test case 1 failed: expected hello, got hello#world 
Test case 2 failed: expected hello, got hello{world} 
Test case 3 failed: expected hello, got hello world 
Test case 4 failed: expected hello, got hello world 
Test case 5 failed: expected hello, got hello world 
Process finished with exit code 0

I this case I believe I was passing in a pointer to memory in the read only space.在这种情况下,我相信我在只读空间中传递了一个指向 memory 的指针。 The struct test_case is built into the code and is read only. struct test_case内置于代码中并且是只读的。 So that when I pass that into the token function it was trying to write to read only.因此,当我将其传递给令牌 function 时,它试图写入只读。 Here is the code that seems to work.这是似乎有效的代码。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
  separator - consume all non-token characters until next token.  
This includes:
    comments:   '#' ... '\n'
    nesting:    '{'
    unnesting:  '}'
    whitespace: ' ','\t','\n'

    *nest is changed according to nesting/unnesting processed
 */
static void separator(int *nest, char **tokens) {
    char c, *s;

    s = *tokens;
    while ((c = *s)) {
        /* #->eol = comment */
        if (c == '#') {
            s++;
            while ((c = *s)) {
                s++;
                if (c == '\n')
                    break;
            }
            continue;
        }
        if (c == '{') {
            (*nest)++;
            s++;
            continue;
        }
        if (c == '}') {
            (*nest)--;
            s++;
            continue;
        }
        if (c == ' ' || c == '\n' || c == '\t') {
            s++;
            continue;
        }
        break;
    }
    *tokens = s;
}

/*
  token - capture all characters until next separator, then consume 
separator,
    return captured token, leave **tokens pointing to next token.
 */
static char *token(int *nest, char **tokens) {
    char c, *s, *t;
    char terminator = '\0';
    s = t = *tokens;
    while ((c = *s)) {
        if (c == '#'
            || c == ' ' || c == '\t' || c == '\n' || c == '{' || c == '}')
            break;
        s++;
    }
    *tokens = s;
    separator(nest, tokens);
    *s = '\0';
    return t;
}


struct test_case {
    char *input;
    int nest;
    char *expected_output;
};


int main() {
    int nest = 0;
    int TESTSEP = 0;
    char *temp_malloc_string;
    if (TESTSEP>0) {
        char *tokens = "# this is a comment\n{nesting {example} 
unnesting}\n  \t end";
        temp_malloc_string = malloc(strlen(tokens)*sizeof(char));
        strcpy(temp_malloc_string, tokens);
        char * t = token(&nest, &temp_malloc_string);
        printf("nest: %d\n", nest);
        printf("tokens: %s\n", t);
        separator(&nest, &temp_malloc_string);

        printf("nest: %d\n", nest);
        printf("tokens: %s\n", temp_malloc_string);
        return 0;
    } else {
        struct test_case test_cases[] = {
            {"hello world",  0, "hello"},
            {"hello#world",  0, "hello"},
            {"hello{world}", 0, "hello"},
            {"hello  world", 0, "hello"},
            {"hello\tworld", 0, "hello"},
            {"hello\nworld", 0, "hello"},
        };

        for (int i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {
            struct test_case test_case = test_cases[i];
            char *tokens = test_case.input;
            printf("len of string is %d\n", strlen(tokens));
            temp_malloc_string = malloc((strlen(tokens)+1)*sizeof(char));
            char * tt = temp_malloc_string;
            if ( temp_malloc_string==NULL ) {
                printf("error!\n");
            }
            strcpy(temp_malloc_string, tokens);
            printf("tm going in: %s\n", temp_malloc_string);

            char *output = token(&test_case.nest, &temp_malloc_string);
            printf("Test case %d: expected %s, got %s\n\t\ttm is now: %s\n",
                   i, test_case.expected_output, output, temp_malloc_string);
            if (strcmp(output, test_case.expected_output) != 0) {
                printf("Test case %d failed: expected %s, got %s\n",
                       i, test_case.expected_output, output);
            }
            free(tt);
            temp_malloc_string = NULL;
        }

        return 0;
    }
}

Now when I run the code I get:现在,当我运行代码时,我得到:

./explore.exe
len of string is 11
tm going in: hello world
Test case 0: expected hello, got hello
                tm is now: world
len of string is 11
tm going in: hello#world
Test case 1: expected hello, got hello
                tm is now:
len of string is 12
tm going in: hello{world}
Test case 2: expected hello, got hello
                tm is now: world}
len of string is 12
tm going in: hello  world
Test case 3: expected hello, got hello
                tm is now: world
len of string is 11
tm going in: hello      world
Test case 4: expected hello, got hello
                tm is now: world
len of string is 11
tm going in: hello
world

Test case 5: expected hello, got hello
                tm is now: world

Process finished with exit code 0

And when I stop at the breakpoint I can write to memory.当我在断点处停止时,我可以写入 memory。

In this modified code I malloc a char* object and copy the string from the struct into that then pass that into the token function.在此修改后的代码中,我将 malloc 和 char* object 中的字符串复制到该结构中,然后将其传递到令牌 function 中。

I'm guess that gdb is protecting me from writing to the.text block in code.我猜 gdb 正在保护我不写入代码中的 the.text 块。

Like I said: I'm a newbie:(就像我说的:我是新手:(

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM