【问题标题】:valgrind complains doing a very simple strtok in cvalgrind 抱怨在 c 中做了一个非常简单的 strtok
【发布时间】:2010-04-02 07:29:06
【问题描述】:

您好,我正在尝试通过使用fread 将整个文件加载到char[] 来标记字符串。 由于某些奇怪的原因,它并不总是有效,并且 valgrind 在这个非常小的示例程序中抱怨。

给定一个像test.txt这样的输入

first
second

还有下面的程序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>


//returns the filesize in bytes
size_t fsize(const char* fname){
  struct stat st ;
  stat(fname,&st);
  return st.st_size;
}

int main(int argc, char *argv[]){
  FILE *fp = NULL;
  if(NULL==(fp=fopen(argv[1],"r"))){
    fprintf(stderr,"\t-> Error reading file:%s\n",argv[1]);
    return 0;
  }
  char buffer[fsize(argv[1])];
  fread(buffer,sizeof(char),fsize(argv[1]),fp);
  char *str = strtok(buffer," \t\n");

  while(NULL!=str){
    fprintf(stderr,"token is:%s with strlen:%lu\n",str,strlen(str));
    str = strtok(NULL," \t\n");
  }
  return 0;
}

编译方式

gcc test.c -std=c99 -ggdb

跑起来

./a.out test.txt

谢谢

【问题讨论】:

  • strtok 已经过时并且有几个问题。不要使用它。
  • 你会推荐什么?对于简单的东西,不一定是线程安全的等等。我仍然觉得它非常有用
  • 嗯,显然没那么简单,否则valgrind不会抱怨。
  • 所以 valgrind 永远不会抱怨明显简单的事情?

标签: c++ c valgrind tokenize strtok


【解决方案1】:

您的buffer 大小应为filesize + 1+1 用于 null 字符。

filesize = fsize(argv[1]);
char buffer[filesize + 1];

此外,fread 不会在字符串末尾放置 \0。所以你必须自己做:

fread(buffer,sizeof(char),filesize,fp);
buffer[filesize] = 0;

【讨论】:

  • 可以将变量(filesize + 1)而不是常量用作数组大小...?
【解决方案2】:

来自site

int main(int argc, char* argv[])
{
  std::string str = "The quick brown fox";

  // construct a stream from the string
  std::istringstream stream(str);

  // use stream iterators to copy the stream to the vector
  // as whitespace separated strings
  std::istream_iterator<std::string> it(stream), end;

  std::vector<std::string> results(it, end);

  // results = ["The", "quick", "brown", "fox"]
}

比处理那些不断敲打你头的讨厌的 C 弦要容易得多。

您知道使用高阶方法有什么好处吗?它占用的屏幕空间更少,更易于理解。

【讨论】:

  • +1,这个问题被标记为 C 和 C++,但很多时候这意味着 我正在编程 C++,但可以使用 C 解决方案,即使在这种情况下代码和文件名似乎表示纯 C。无论如何,这是值得的(使用 C++ 的人肯定会读到这个),即使它可能不适合用户。
【解决方案3】:

buffer 不是以空值结尾的。你需要让它比文件的大小大一个字节,你需要将最后一个字节设置为\0

【讨论】:

    【解决方案4】:

    你的缓冲区必须是filesize + 1,你还需要设置终止0:

    int size = fsize(argv[1]);
    char buffer[size + 1];
    buffer[size] ='\0';
    

    另外,您可能应该在堆上而不是堆栈上分配缓冲区...

    【讨论】:

      【解决方案5】:

      您的缓冲区太小。试试这个:

      int fileSize = fsize(argv[1]);
      char buffer[fileSize + 1]; 
      buffer[fileSize] = 0;
      

      就在您致电fread之前。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-12
        • 1970-01-01
        • 1970-01-01
        • 2019-08-14
        • 1970-01-01
        • 2015-02-03
        • 1970-01-01
        相关资源
        最近更新 更多