【问题标题】:C: Exception thrown at 0x0FFB0BA0 (ucrtbased.dll)C: 在 0x0FFB0BA0 (ucrtbased.dll) 处抛出异常
【发布时间】:2017-04-12 19:21:48
【问题描述】:

我正在开发一个程序,要求用户输入一个单词以及用户想要从该单词中复制的字母数。该程序在我使用 Compile Online 时有效,但是当我在 Micrsoft Visual Studio 中运行该程序时,在我输入要复制的单词后程序冻结。我运行调试器,发现如下所示的错误。我认为,from googling,我正在写超过为我的数组预留的内存量?我应该使用 malloc 来解决这个问题吗?下面贴出错误和代码(链接到原始stackoverflow thread

在 lab1113problem7.exe 中的 0x0FFB0BA0 (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突写入位置 0x00B80000。

lab1113problem7.exe 中 0xFEFEFEFE 处的未处理异常:0xC00001A5:检测到无效的异常处理程序例程(参数:0x00000003)。

程序“[7196] lab1113problem7.exe”已退出,代码为 0 (0x0)。

程序:

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

char *copywords(char *dest, const char *source, size_t n);

int main(void) {
    char words[50];
    char newwords[50];
    int num;

    for (;;) {
        printf("Type a word, or type 'quit' to quit: ");
        if (scanf("%49s", words) != 1) {
            printf("Invalid input!\n");
            return 0; 
        }
        if (!strcmp(words, "quit")) {
            printf("Good bye!\n");
            return 0; 
        }
        printf("Type the # of chars to copy: ");
         if (scanf("%d", &num) != 1) {
            printf("Invalid input!\n");
            return 0; 
        }
        copywords(newwords, words, num);
        printf("The word was %s\n", words);
        printf("and the copied word is %s\n", newwords);
    }
}

char *copywords(char *dest, const char *source, size_t n) {
    size_t i;
    for (i = 0; i < n && source[i] != '\0'; i++) {
        dest[i] = source[i];
    }
    dest[i] = '\0';
    return dest;
}

【问题讨论】:

  • 使用调试器更有效地帮助您找到问题。对于初学者来说,它到底是哪一行代码崩溃了。调试器告诉你。并使用调试器检查num 的值。然后继续继续逐行执行程序。
  • 我没有发现任何问题。但是您确定这是您正在运行的实际代码吗?例如,如果将printf("Yes, this is the actual code!\n");添加为main的第一条语句,然后运行程序,你会看到那个输出,并且程序仍然无法运行吗?
  • @kaylum 只要我输入一个单词,调试器就会停止并抛出异常。
  • @Markovnikov 好吧,你已经知道了。此外,调试器不会抛出异常,您的程序会抛出调试器告诉您的异常。另外,异常是从代码的哪一部分引发的?查看“调用堆栈”窗口/窗格/区域。
  • @Markovnikov 是的,但是您可以从调试器中获取所谓的“堆栈跟踪”。这可以准确地告诉您哪一行代码触发了崩溃。显然,您还没有学会有效地使用调试器。请这样做。这将是美好的时光。

标签: c arrays memory


【解决方案1】:

一些调试代码以确保您的字符串按预期工作:

// Place this at the top of your file, after your `#include` statements 
// and use it in place of the 50s in your array defines.
#define MAX_ARRAY_SIZE 50

char *copywords(char *dest, const char *source, size_t n) {
    size_t i;
    for (i = 0; i < n && source[i] != '\0'; i++) {
        if(i >= MAX_ARRAY_SIZE)
        {
            printf("I just blew up memory at %i\n", %i);
        }
        dest[i] = source[i];
    }
    dest[i] = '\0';
    return dest;
}

注意:您可以在 for 循环中检查每次迭代的数组大小,以确保您没有超出缓冲区。

不是直接的答案,而是比使用 cmets 更容易尝试的方法。如果 printf 被触发,你就知道发生了不好的事情......

更好的是,因为您将大小作为n 传递,您可以在每次循环开始之前检查数组大小并立即处理错误数据。

char *copywords(char *dest, const char *source, size_t n) {
    if(n >= MAX_ARRAY_SIZE) 
    {
        printf("Array will overflow by %d bytes- truncating\n", n - MAX_ARRAY_SIZE);
        n = MAX_ARRAY_SIZE;
    }

【讨论】:

  • 感谢您的帮助。我尝试了调试代码,MSVS 不会让它们执行 - 程序不会让我输入一个单词,并且调试器不断询问“将异常传递给正在调试的程序?”无论我说是还是不是,都会出现与我原来的帖子相同的错误。我完全不知道出了什么问题,也不知道如何解决它。
  • 好的,错误是在调用此代码之前。在每一行之前或单步执行代码之前在调试器中放置断点。 (或者,如果您不知道如何执行此操作,请在包含“我在这里\n”类型消息的主循环中的每一行代码之后放置一个 printf() 语句,然后查看它有多远。跨度>
  • 我在代码中添加了打印语句。在我输入一个单词之前它工作得很好。编译器给出的一个警告是“'scanf_s'没有为格式字符串传递足够的参数” - 我应该使用 scanf 以外的东西来获取字符串吗? getchar 或 fgets 会起作用吗?如果是这样,我如何格式化这些以使用退出代码?
  • @Markovnikov 为什么当你使用 scanf 而不是 scanf_s 时,MSVC 会谈论 scanf_s?
  • Microsoft Visual Studio 强制程序员使用 scanf_s,因为 scanf 被视为不安全。
猜你喜欢
  • 1970-01-01
  • 2021-06-11
  • 2019-04-01
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
相关资源
最近更新 更多