【问题标题】:Access violation when calling strtok(); C++调用 strtok() 时访问冲突; C++
【发布时间】:2014-08-30 12:24:49
【问题描述】:

这段代码有问题:

char KernelFS::doesExist(char* fname){
    char part;
    char name[8];
    char ext[3];

    char* token;

    token = strtok(fname, "\\");
    strncpy(&part, token, 1);

    token = strtok(fname, "\\");
    strncpy(name, token, 8);

    token = strtok(fname, "\\");
    strncpy(ext, token, 3);

    return 0;
}

当我在第一次调用 strtok(...) 时运行它会编译并中断 - 访问冲突写入位置 ... 不知道为什么:(

我调用这个函数:

KernelFS::doesExist("X:\test.exe");

重点是将fname char数组分成3个数组; 一个为分区的名称, 一个为文件名, 一个用于文件扩展名;

感谢您的帮助! :)

【问题讨论】:

  • 为什么当你有std::string时,人们会使用原始字符数组。
  • 在填写完partnameext之后,您永远不会使用它们。如果您修改代码以使用它们,请记住这些不是字符串(您创建的字符缓冲区没有空终止符)
  • 还有一件事:\t 有一个特殊的含义,如果你想要一个 \ 分隔符然后使用X:\\test.exe

标签: c++ strtok


【解决方案1】:

在你的例子中:

KernelFS::doesExist("X:\test.exe");

"X:\test.exe" 实际上是const char* 类型,你不能修改它。该原始字符串文字是在受保护的内存区域内分配的,因此您遇到了错误。

char * strtok ( char * str, const char * delimiters );

str - 请注意,此字符串被修改分解为更小的字符串(标记)。 或者,可以指定一个空指针,在这种情况下,函数会继续扫描之前成功调用函数的位置。

如果您真的想使用<cstring> 库(虽然不建议),您应该将字符串分配到堆栈上,而不是从程序符号区域获取它。

char path[] = { "X:\\test.exe" };
KernelFS::doesExist(path);

但是,建议您切换到<string> 库。

【讨论】:

  • 另外你应该检查KernelFS::doesExist()没有收到NULL指针并且strtok()没有返回NULL。
  • +1, @Alek988Alek 之后,请密切注意strncpy 不会在扩展名为 3 个字符宽的情况下使用 nullchar 终止文件扩展名。您的缓冲区似乎都是 1 字符短。
【解决方案2】:

我建议如下修改:

char KernelFS::doesExist(char* fname)
{
    // Our variables.
    char part[2];
    char name[9];
    char ext[4];        
    char* token;

    // Initialize variables.
    memset(part, '\0', 2);
    memset(name, '\0', 9);
    memset(ext, '\0', 4);

    // If we receive an invalid string:
    if (fname == NULL)
        return -1; // Return error.

    // Process.
    if ((token = strtok(fname, "\\")) != NULL)
        strncpy(part, token, 1);
    if ((token = strtok(fname, "\\")) != NULL)
        strncpy(name, token, 8);
    if ((token = strtok(fname, "\\")) != NULL)
        strncpy(ext, token, 3);

    // If we retrieved the 3 variables:
    if (strlen(part) > 0 && strlen(name) > 0 && strlen(ext) > 0)
    {
        // Do something with part, name and ext here.
    }

    // Return success.
    return 0;
}

正如 Piotr S. 所说,请注意使用有效的 char *(而不是 const char * 或其他任何东西)调用此函数。

【讨论】:

    猜你喜欢
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    相关资源
    最近更新 更多