Etberzin
2015-07-01 17:11
采纳率: 100%
浏览 2.1k
已采纳

C程序内存不能为read错误,包含文件和内存操作

各个方法每个都没问题,放一块儿就冒出个不明原因的错误

#include <stdio.h>
#include <math.h>
#include <time.h>

//get time difference
//days from 2015/6/9 to here.
int getTD();
//free()!
char* getTextFileContent(char*);
long getFileSize(FILE*);
//free()!
char* mStrCat(char*, char*);

int main()
{
    int TD = getTD() + 1;

    char buf[100];
    getcwd(buf, 100);

    char *listPath = mStrCat(buf, "\\plan.txt");
    //DEBUG
    printf("%s\r\n", listPath);

    char* text = getTextFileContent(listPath);
    free(listPath);
    printf("%s", text);
    text = (text == NULL) ? "" : text;

    system("cls");
    printf("高考后第[ %d ]天\r\n", TD);
    printf("Tasks:\r\n %s\r\n", text);
    system("pause & exit");

    free(text);

    return 0;
}

int getTD()
{
    struct tm tmptm = {0, 0, 0, 9, 5, 2015 - 1900};
    long startT = mktime(&tmptm);
    long nowT = time(NULL);
    //seconds
    long TDs = nowT - startT;
    //days
    double TDd = (double)TDs;
    TDd = TDd / (60 * 60 * 24);
    TDd = floor(TDd);
    return (int)TDd;
}

char* getTextFileContent(char *path)
{
    FILE *fp = fopen(path, "r");
    if(fp == NULL) 
        return NULL;
    long size = getFileSize(fp);
    int chLen = sizeof('\0');
    char *ptr = (char*)malloc(size + chLen);
    //block 作为这块内存区的起始指针将被作为字符串指针返回,ptr 经过运算后将指向内存区结尾。
    char *block = ptr;
    if(ptr == NULL)
    {
        return NULL;
    }

    int c;
    char ch;
    //依次将fgetc 获得的字符填入内存区。
    while((c = fgetc(fp)) != EOF)
    {
        ch = (char) c;
        memcpy(ptr, &ch, chLen);
        //移动ptr 到下一个待填入的地址。
        (int)ptr += chLen;
    }
    char endC = '\0';
    memcpy(ptr, &endC, chLen);

    return block;   
}

long getFileSize(FILE* f)
{
    long size = (fseek(f, 0L, SEEK_END) != 0) ? (ftell(f)) : -1;
    rewind(f);

    return size;
}

char* mStrCat(char *str1, char *str2)
{
    int str1Len = strlen(str1) + 1;
    int str2Len = strlen(str2) + 1;
    int byteNum = (str1Len + str2Len - 1) * sizeof(char);
    char *block = (char*)(malloc(byteNum));
    if(block == NULL)
        return NULL;

    memmove(block, str1, str1Len * sizeof(char));
    strcat(block, str2);

    return block;
}

文件内容可以正常输出,说明文件读取的部分大概没问题,mStrCat 经测试也没发现问题,但程序死活执行不到 system("cls") ,一到这儿Windows就会弹窗提示。
图片说明

文件内容可以正常输出:
图片说明

另外,运行程序的时候360报毒了,一个QVM。。。,然后运行几次之后那个cmd窗口无法关闭了(点什么都没反映,但光标在闪)。打开的任务管理器也变成了这样:
图片说明
自然,没能杀掉cmd,最后连资源管理器都不正常了,通过重启解决。(一个小练习而已杀伤力没这么大吧)

P.S. 通过TCC 编译


改动后的getTextFileContent 代码:(实际上没什么改动,但至少能用了)

 char* getTextFileContent(char *path)
{
    FILE *fp = fopen(path, "r");
    if(fp == NULL) 
        return NULL;

    long size = getFileSize(fp);

    int chLen = sizeof(char);
    char *ptr = (char*)malloc(size + chLen);
    char *block = ptr;
    if(ptr == NULL)
    {
        return NULL;
    }

    int c;
    char ch;
    while((c = fgetc(fp)) != EOF)
    {
        ch = (char)c;
        memcpy(ptr, &ch, chLen);
        ptr += chLen;
    }
    ch = '\0';
    memcpy(ptr, &ch, chLen);

    fclose(fp);
    return block;
}

文件大小为275b 时读取汉字都没问题(I don't know why ...),但到1.27k(全英文)时就又冒出了内存不能为written 错误,一瞬间想到当初在Android 上写的个文件复制程序会不时的冒出Segmentation Fault……

哪位大神来搭救一下!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

9条回答 默认 最新

  • 天已青色等烟雨来 2015-07-06 07:46
    已采纳

    有两处严重的错误:
    @1:text = (text == NULL) ? "" : text; 如果text为null,text会指向一个字符串常量,释放时候必崩溃
    @2:long size = (fseek(f, 0L, SEEK_END) != 0) ? (ftell(f)) : -1; 此处逻辑错误,long size = (fseek(f, 0L, SEEK_END) == 0) ? (ftell(f)) : -1;才正确

    点赞 打赏 评论
  • xulingwei1998 2015-07-01 17:21

    虽然我不懂这些,但是那个任务管理器双击边框就能恢复吧

    点赞 打赏 评论
  • Soulic 2015-07-01 23:12

    有个问题,在getTextFileContent()函数中没有关闭文件

    点赞 打赏 评论
  • 91program 2015-07-01 23:29

    应该是访问越界了
    你没有调试一下,看看具体是哪一行引起这个错误的?

    编程,调试是很重要的手段。像你这样的问题,在实际工作中也经常出现:单个模块没有问题(其实可能是有问题,但没有表现出来),但集成在一起时就有问题了。
    这时,可以通过调试来观察每个模块的入口条件、及执行过程来发现问题。

    点赞 打赏 评论
  • oyljerry 2015-07-01 23:44

    设置断点,跟踪一下,你有地方指针越界操作了。多看看各个变量的有效值。

    点赞 打赏 评论
  • Kwolve 2015-07-02 01:21

    重点调试下面部分代码“:
    struct tm tmptm = {0, 0, 0, 9, 5, 2015 - 1900};
    long startT = mktime(&tmptm);
    long nowT = time(NULL);
    //seconds
    long TDs = nowT - startT;
    //days
    double TDd = (double)TDs;
    TDd = TDd / (60 * 60 * 24);
    TDd = floor(TDd);
    这个算法没有处理,肯能导致一些问题。

    点赞 打赏 评论
  • dreamwatchman 2015-07-02 04:41

    感觉80%就是指针操作时,内存越界了。仔细调试一下,看看各个指针变量

    点赞 打赏 评论
  • gggfddhj 2015-07-02 08:26

    一步步的引起来,慢慢的查问题

    点赞 打赏 评论
  • kongslly 2015-07-02 08:44

    int chLen = sizeof('\0');
    这个不要用sizeof要用strlen

    char block = (char)(malloc(byteNum));
    分配空间指定大小需要

    点赞 打赏 评论

相关推荐 更多相似问题