奇怪的行为计算文件中的行

时间:2012-02-21 21:06:13

标签: c algorithm file gcc

寻找一种从配置文件中读取参数的方法我找到了一种很好的方法来做到这一点但事情是当我尝试计算线条时发生了一些非常奇怪的事情。

这是代码:

FILE *file = fopen("config", "r");

char line[100];
int linenum = 0;
//int foo;  Uncomment and it starts to working, doesn't matter if you rename it.

while(fgets(line, sizeof(line), file) != NULL) {
    char option[4];
    char arg[100];

    if (line[linenum] == '#') 
        continue;
    linenum++;

    if (sscanf(line, "%s %s", option, arg) != 2)
        fprintf(stderr, "Syntax error, line %i\n", linenum);

配置文件如下所示:

#config file
option1
option2
option3

结果是:

Syntax error, line 1
Syntax error, line 0
Syntax error, line 0

但是如果我在while循环之前声明一个带有任何名称的int变量,它就会开始工作!

结果是:

Syntax error, line 1
Syntax error, line 2
Syntax error, line 3

世界上到底发生了什么?我的思绪会被打击,也许这是一种愚蠢的事情,但我认为没有任何理由。

4 个答案:

答案 0 :(得分:3)

您的option数组太小(char option[4]),因此sscanf会覆盖其他内容。未定义的行为。

通常,当奇怪的事情无缘无故地发生时(就像你声明一个无关的变量一样“工作”),这是因为内存问题。由于您提到gcc,因此您可能需要查看valgrind

答案 1 :(得分:1)

至少看起来像这部分:

if (line[linenum] == '#') continue;
  linenum++;

将无法提供所需的结果,因为您正在检查行开头的注释字符。

答案 2 :(得分:0)

if (sscanf(line, "%s %s", option, arg) != 2)

这会溢出option数组并覆盖linenum对象。

答案 3 :(得分:0)

每当你看到这样的奇怪行为时,你应该开始寻找内存溢出错误。典型症状包括:

  1. 如果添加或删除未使用的变量,则代码可以正常工作或停止工作。
  2. 无变化的变量。
  3. 有时正常运行的代码,并使用相同的输入在其他时间崩溃。
  4. 使用相同输入在调用之间产生不同结果的代码。
  5. 在这种情况下,正如其他答案所指出的那样,您有两个潜在的与内存相关的错误:

    if (line[linenum] == '#') continue;

    应为if (line[0] == '#') continue;

    否则,linenum > 99时索引无效。

    if (sscanf(line, "%s %s", option, arg) != 2){

    如果输入字符串太长,

    将超出optionarg变量。 (您看到的错误是因为文本(例如 option1)超过4个字符并溢出option。您可以通过多种方式解决此问题:

    • 增加option的大小。您需要知道输入字符串的最大长度才能选择合适的大小。
    • 限制复制到option的字符数:
      if (sscanf(line, "%3s %99s", option, arg) != 2){
      这可能会导致长输入字符串的意外输出,因为arg将包含option中字符串的其余部分(如果它被截断)。
    • 根据http://linux.die.net/man/3/sscanf,您可以使用a修饰符告诉sscanf在读取字符串时为字符串分配内存:
      char **str1, **str2;
      if (sscanf(line, "%as %as", &str1, &str2) != 2){