程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> malloc-C程序內存不能為read錯誤,包含文件和內存操作

malloc-C程序內存不能為read錯誤,包含文件和內存操作

編輯:編程綜合問答
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……

哪位大神來搭救一下!

最佳回答:


有兩處嚴重的錯誤:
@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;才正確

Etberzin
Etberzin
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved