从不同位置调用相同函数时的行为不一致

时间:2014-06-04 17:29:44

标签: c function pointers printf

作为团队作业的一部分,我必须创建一个程序来读取程序集源文件并为特定体系结构生成二进制代码。

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

我遇到的问题是,当从 main()调用 toks_print()时,最后两行(标记)难以辨认,而 toks_print()< / strong>从 read_assembly_file()调用,结果是一致的。

这是打印到stdout上的输出:

这是读取的文件:
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;
}

1 个答案:

答案 0 :(得分:2)

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

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

使用read_assembly_program()绕过此传递向buffer引用buffer或在堆上分配malloc()


<强>更新

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

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