【问题标题】:Crash on write file procedure !closed写入文件过程崩溃!关闭
【发布时间】:2012-12-07 08:35:30
【问题描述】:

我编写了一个必须将二维数组写入文件的过程。代码如下:

void Level::loadLevel(){
    int levelmap[15][9];
    FILE *fp = fopen("resources/lvls/loc1.map", "wb");  
    for (int i=0;i<=15;i++){
        for(int j=0;j<=9;j++){
            levelmap[i][j]=i+j;
            }
    }
    char asd[255];

    for (int i=0;i<=15;i++){
        for(int j=0;j<=9;j++){
            char *buffer=itoa(levelmap[i][j],asd,1);
            fwrite(buffer,2,sizeof(buffer),fp);
            };
        };
    fclose(fp);
 }

它正在编译,但在调用此函数应用程序时崩溃。我将其称为 cocs2d-x 菜单项的 menu_selector 属性。为什么会崩溃?

更新:更改为文件流广告效果很好

【问题讨论】:

  • 文件真的打开了吗?检查fopen 的返回值。您还可以在循环中一对多地索引您的数组。
  • 它是如何崩溃的?抛出什么异常?哪条线路有问题?您是否尝试过调试此代码?
  • 是的,它已经打开了。文件清除并关闭。试过这段代码: void Level::loadLevel(){ FILE* fp = fopen("resources/lvls/loc1.map", "w+"); fwrite("test",1,sizeof("test"),fp); fclose(fp);} 但它返回 Run-Time Check Failure #0
  • 您无法写入 apk 文件。您只能写入 sdcard(如果您有权限)或 CCFileUltis 中的 getWriteablePath()。

标签: c++ visual-c++ crash cocos2d-x


【解决方案1】:

不只是上面提到的错误……

  1. 确保您的文件夹“resources/lvls/”确实存在。 fopen 不创建文件夹!

  2. itoa 的第三个参数 - 基数(值的基数;必须在 2–36 范围内。)

  3. 你真的想把它写成二进制格式的 int 字符串表示吗?打开二进制输出文件意味着您将在那里写入原始数据。您可以使用下一个代码将 int 数组保存到/从文件中加载:

'

void saveLevel()
{
    int levelmap[15][9];
    FILE *fp = fopen("loc1.map", "wb");  
    for (int i=0;i<15;i++){
        for(int j=0;j<9;j++){
            levelmap[i][j]=i+j;
        }
    }

    for (int i=0;i<15;i++){
        fwrite(levelmap[i], sizeof(int), _countof(levelmap[i]), fp);
    };

    fclose(fp);
}

void loadLevel()
{
    int levelmap[15][9];

    FILE *fp = fopen("loc1.map", "rb");  

    for (int i=0;i<15;i++){
        fread(levelmap[i], sizeof(int), _countof(levelmap[i]), fp);
    };
    fclose(fp);

}

'

【讨论】:

  • 您只阅读了[i] 数组级别并没有将其放回levelmap。如果我将分配该 fread 文本,它将返回整个 [j] 数组级别吗?
  • C++ 中的一维数组是一个固态内存块。所以你可以用一行代码来读写整个数组,但是你不能用包含动态分配字段的类数组来做到这一点......你只需要了解对象是如何放置在内存中的。
【解决方案2】:

您在几个地方超出了数组边界,因此您正在破坏内存。例如:

int levelmap[15][9];
//           ^^  ^

// ...

for (int i=0;i<=15;i++){
    //        ^^^^
    for(int j=0;j<=9;j++){
                 ^^^
        levelmap[i][j]=i+j;
    }
}

在数组索引的for 循环条件中使用&lt;= 是一个危险信号。这样做几乎总是错误的,所以每次看到代码时都要仔细检查。

还有:

char *buffer= /* ... */;
// ...
fwrite(buffer,2,sizeof(buffer),fp);

没有做你认为它做的事情,因为sizeof(buffer) 是指针的大小,与缓冲区中的字符数无关。为什么将2 作为元素的大小传递给fwrite()

【讨论】:

  • 我只是增加了数组的大小。谢谢你。但这并不完全是崩溃者
【解决方案3】:
char *buffer=itoa(levelmap[i][j],asd,1);

itoa 的最后一个参数是 base。它应该是 10 而不是 1(参见 http://www.cplusplus.com/reference/cstdlib/itoa/


void Level::loadLevel(){
    int levelmap[15][9];
    FILE *fp = fopen("resources/lvls/loc1.map", "wb");  
    for (int i=0;i<=15;i++){
        for(int j=0;j<=9;j++){
            levelmap[i][j]=i+j;
            }
    }

如果 i == 15 且 j == 9,则超出数组的边界(levelmap[15][9] 表示 levelmap[0..14][0..8])

将循环中的条件更改为 i

【讨论】:

  • Run-Time Check Failure #0
  • 但最后文件被更改了
  • 好的,我想它已经解决了。现在遇到了 libcoco2d 的问题,它返回 run-rime check failure #0。我想都是因为它是非cocos函数
  • 我不明白。什么意思?
  • 我的回答被某人(不一定是你)否决了。我想知道,为什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 2019-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多