Malloc-память закрытого члена перезаписывается после вызова функции другого объекта (того же класса) - PullRequest
0 голосов
/ 17 июня 2019

Функция, вызываемая объектом output того же класса, что и объект input, кажется, вызывает непредвиденное поведение и перезаписывает объект input 'malloc данные приватного члена (адреса указателя остаются теми же)

Для объекта output оба значения *fileStr и *p_file имеют значение NULL, а для input обе точки данных
И CASE1 / CASE2, или комбинация каждого #ifdef приведет к изменению данных input.fileStr
input.fileStr сами данные malloc 'изменяются class1::open при вызове (вызывается только input) - иначе это NULL-указатель по умолчанию

Заголовок

class class1
{
private:
    FILE *p_file = NULL;
    char *fileStr = NULL;
    bool encrypt_step1();
public:
    bool open(char *pathto);
    bool create(char *pathto);
    bool encrypt();
    ~class1();
};
bool sub_function(char *pathIN);

Исходный код

bool class1::open(char *pathto)
{
    if (PathFileExistsA(pathto))
        this->p_file = fopen(pathto, "rb+");
    else
        return 0;
    if (!(this->p_file))
    {
        printf("Can't open\n");
        return 0;
    }
    fseek(p_file, 0, SEEK_END);
    long filesize = ftell(p_file);
    fseek(p_file, 0, SEEK_SET);
    this->fileStr = (char*)malloc(filesize+1);
    this->fileStr[(fread(this->fileStr, 1, filesize, this->p_file))] = '\0';
    return 1;
}
bool class1::create(char *pathto)
{
#ifdef CASE1
    if (PathFileExistsA(pathto))
    {
        char pathtobak[MAX_PATH];
        strcpy(pathtobak, pathto);
        strcat(pathtobak, ".bak");
        int i = 0;
        char a[11];
        if (PathFileExistsA(pathtobak))
        {
            while (1)
            {
                i++;
                *a = '\0';
                itoa(i, a, 10);
                char *reset = pathtobak + strlen(pathtobak);
                strcat(pathtobak, a);
                if (!PathFileExistsA(pathtobak))
                    break;
                *reset = '\0';
            }
        }
        std::experimental::filesystem::copy_file(pathto, pathtobak);
    }
#endif
#ifdef CASE2
    this->p_file = fopen(pathto, "wb");
#endif
#ifndef NOERRORS
    if (this->p_file == NULL)
        return 0;
    else
        return 1;
#endif
}
class1::~class1()
{
    if (this->fileStr)
    {
        free(this->fileStr);
        this->fileStr = NULL;
    }
    if (this->p_file)
    {
        fclose(this->p_file);
        this->p_file = NULL;
    }
}
bool sub_function(char *pathIN)
{
    class1 input;
    input.open(pathIN);
    input.encrypt();//omitted since this should be irrelevant
    char pathOUT[MAX_PATH];
    strcpy(pathOUT, pathIN);
    char *OUText = pathOUT;
    OUText += (strlen(pathOUT)-3);
    *OUText = '\0';
    strcat(pathOUT, "ext");
    class1 output;
    output.create(pathOUT);//bug here
    char *next = input.get_fileStr();
    ...
}

Это похоже на нарушение доступа к памяти, но даже CASE1, который просто ищет дубликаты файлов с использованием только локальной переменной, по-прежнему вызывает непредвиденное поведение, поэтому у меня есть проблемы с определением причины

Кажется, память уже освобождена

Наиболее вероятная причина - пометка памяти как свободной, но я не освобождаю ее за пределами деструктора, но при дальнейшем запуске программы после вызова деструктора input free(input.fileStr) произойдет сбой с is_block_type_valid(header->_block_use) исключением < бр />

Актуальная проблема с рабочим примером

Исходный код, начиная с sub_function::input.encrypt()

bool class1::encrypt_step1()
{
    bool *strBOOL_11_00 = (bool*)malloc(((strlen(this->fileStr)) + 1) * ((sizeof(bool)) * 8));
    bool *strBOOL_10_01 = (bool*)malloc(((strlen(this->fileStr)) + 1) * ((sizeof(bool)) * 8));
    bool *strBOOL_10_11 = (bool*)malloc(((strlen(this->fileStr)) + 1) * ((sizeof(bool)) * 8));
    char *fileStrIt = this->fileStr;
    char *fileStrIt2 = ((this->fileStr) + 1);
    bool *next1100 = strBOOL_11_00;
    bool *next1001 = strBOOL_10_01;
    bool *next1011 = strBOOL_10_11;

    //translating to binary array iterating through pointers above one by one happens here
    //char->bin/encrypt/bin->char
    //ommited

    //reallocation to fit new encrypted and translated back to char that caused issues
#ifdef ISSUE
    char *fileStr_temp = (char *)realloc(this->fileStr, ((next1011 - strBOOL_10_11) + (next1001 - strBOOL_10_01) + (next1100 - strBOOL_11_00) + 1));
    if (!fileStr_temp)
        return 0;
    //original fileStr points at freed memory
#endif

#ifdef CORRECT
    char *fileStr_temp = (char *)realloc(this->fileStr, ((next1011 - strBOOL_10_11) + (next1001 - strBOOL_10_01) + (next1100 - strBOOL_11_00) + 1));
    if (!fileStr_temp)
        return 0;
    else
        this->fileStr = fileStr_temp;//original fileStr points at new adress with reallocated data
#endif
    free(strBOOL_11_00);
    strBOOL_11_00 = NULL;
    free(strBOOL_10_01);
    strBOOL_10_01 = NULL;
    free(strBOOL_10_11);
    strBOOL_10_11 = NULL;
    return 1;
}
bool class1::encrypt()
{
    encrypt_step1();
    ...//other steps (irrelevant)
    return 1;
}
...