【问题标题】:Inconsistent behaviour when invoking same function from different places从不同位置调用相同函数时的行为不一致
【发布时间】:2014-06-04 17:29:43
【问题描述】:

作为团队任务的一部分,我必须创建一个程序来读取汇编源文件并为特定架构生成二进制代码。

我创建了函数 tokenize 来根据提供的模式将字符串拆分为标记。

我遇到的问题是,当从 ma​​in() 调用 toks_print() 时,最后两行(令牌)难以辨认,而当 toks_print() 从 read_assembly_file() 调用,结果是一致的。

这是打印到标准输出的输出:

这是读取的文件:
ldr r0,=0x20200004
ldr r2,[r0]
cmp r2,r0
andeq r0,r0,r0

打印 4 个令牌:
ldr r0,=0x20200004
ldr r2,[r0]
cmp r2,r0
andeq r0,r0,r0

打印 4 个令牌:
ldr r0,=0x20200004
ldr r2,[r0]
c¿
\370\277_\377¿


我的问题是:为什么会这样? 我确定它与指针有关 但对于我的生活,我无法弄清楚。 我尝试过的任何其他文件也会发生这种情况:最后几行丢失或 无法辨认。

为了完整起见,这是 gpio_0.s 的内容:
ldr r0,=0x20200004
ldr r2,[r0]
cmp r2,r0
andeq r0,r0,r0

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

//////////////////////////////////////////////////////////////////////

typedef struct Tokens
{
    char **toks;
    unsigned int tokno;
} Tokens;


Tokens *toks_new() 
{   
    Tokens *tokens = malloc(sizeof(Tokens));
    tokens->toks   = malloc(sizeof(char **));
    return tokens;
}


void toks_free(Tokens *tokens)
{
    free(tokens);
    free(tokens->toks);
}


void toks_print(Tokens *tokens)
{
    printf("Printing %i tokens:\n", tokens->tokno);
    for (int i = 0; i < tokens->tokno; i++) 
    {
        printf("%s\n", tokens->toks[i]);
    }
    printf("\n\n");
}


Tokens *tokenize(char *str, const char *delim)
{
    Tokens *tokens = toks_new();
    for (int n = 0; ; n++)
    {
        if (n != 0) str = NULL;
        char *token = strtok(str, delim);
        if (token == NULL)
        {
            tokens->tokno = n;
            break;
        } 
        tokens->toks[n] = token;
    }
    return tokens;
}

////////////////////////////////////////////////////////////////////////////////

Tokens *program = NULL;

////////////////////////////////////////////////////////////////////////////////

void read_assembly_program(const char *filepath)
{
    FILE *file = fopen(filepath, "rt");

    fseek(file, 0, SEEK_END);
    long bytes = ftell(file);
    rewind(file);

    char buffer[bytes];
    fread(buffer, 1, bytes, file);

    // Without this I get an indecipherable line at the end... But why?
    buffer[bytes-1] = '\0';

    // What is printed is exactly what I expect, the whole content of the file
    printf("This is the file read:\n%s\n\n\n", buffer);

    program = tokenize(buffer, "\n");
    // This prints the tokens as expected
    toks_print(program);
}

////////////////////////////////////////////////////////////////////////////////

int main(int argc, char **argv) 
{
    const char * file = "gpio_0.s";

    read_assembly_program(file);

    // But here the last two lines messed up!
    toks_print(program);

  return EXIT_SUCCESS;
}

【问题讨论】:

    标签: c function pointers printf


    【解决方案1】:

    tokenize() 将对buffer 的引用存储到program 引用的数据中。

    buffer 被声明为 read_assembly_program() 的本地,因此在离开 read_assembly_program() 后内存不再有效。

    要绕过此传递到read_assembly_program(),请使用buffer 的引用或使用malloc() 在堆上分配buffer


    更新

    两个(不太好的)替代解决方案:

    • 全局定义缓冲区。
    • 将“本地”缓冲区声明为static

    【讨论】:

    • 我想我明白发生了什么......但是如果我不想在堆上分配缓冲区甚至随身携带它怎么办,因为一旦我在 read_assembly_program() 我是完成了,我不再需要它了吗?
    • 编译器抱怨“可变长度数组声明不能有'静态'存储持续时间。”就是这样,我想在完成后摆脱缓冲区,并能够使用我的程序变量从程序中的任何位置访问文本。显然我必须重新考虑 tokenize() 的实现方式。
    猜你喜欢
    • 2020-01-21
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2019-08-02
    • 2022-06-30
    • 1970-01-01
    • 1970-01-01
    • 2021-06-04
    相关资源
    最近更新 更多