debugging 无法在CLION IDE中使用gdb访问地址处的内存,如何设置gdb?

wdebmtf2  于 2023-01-17  发布在  其他
关注(0)|答案(1)|浏览(185)

在调试器中停止时,当我尝试将内存值设置为0x00时,收到错误“无法访问地址为0x100403055的内存”。
是否需要设置特殊开关才能启用设置操作?
下面是我的完整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;
    }
}

token函数中有一个注解行,我在其中放置了一个断点并将其放入gdb调试器中,代码应该在指针 *s的地址处写入一个'\0'以截断字符串。
当我在调试器中检查's'变量时,我得到以下结果:

(gdb) x s
  0x100403055:  0x726f7720

当我尝试设置变量时,我得到:

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

我正在使用CLION IDE,我是一个新手。我不确定是IDE的问题,用户的问题,还是一些外部内存保护机制阻止了这个。有人知道如何使这个工作吗?
下面是IDE的屏幕截图:

当我运行代码时(不使用调试器),我得到以下输出:

./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
d6kp6zgx

d6kp6zgx1#

在这种情况下,我相信我传递了一个指向只读空间中内存的指针,结构体test_case内置在代码中,是只读的,所以当我传递到令牌函数时,它试图写为只读,下面是看起来工作的代码。

#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;
    }
}

现在当我运行代码时,我得到:

./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

当我在断点处停止时,我可以写入内存。
在这段修改过的代码中,我malloc了一个char* 对象,并将字符串从结构体复制到,然后将其传递给token函数。
我猜gdb是为了防止我在代码中写入.text块。
就像我说的:我是新手:(

相关问题