gpt4 book ai didi

c++ - 在类 File 和 Buffer 中查找段错误

转载 作者:行者123 更新时间:2023-11-30 05:20:31 26 4
gpt4 key购买 nike

这是 this one 的后续问题.

我通过向类 FileBuffer 添加复制构造函数和赋值构造函数来修复双重释放和内存损坏。但是该远程服务器报告存在段错误。有没有办法导致类 FileBuffer 段错误?我认为段错误通常与堆栈有关。但是我在这两个类中没有堆栈操作。

缓冲区.h

#ifndef __BUFFER_H__
#define __BUFFER_H__

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

class Buffer
{

private:
char * buffer;
int size;
Buffer(const Buffer &);
Buffer& operator=(const Buffer &);

public:
Buffer(int size);
~Buffer();
void reverse(int size);


friend class File;
};

#endif

缓冲区.cc:

#include "Buffer.h"
#include "Exception.h"


Buffer::Buffer(int size)
{
this -> size = size;
this -> buffer = (char *)malloc(size);
if(this -> buffer == NULL)
throw Exception(errno);
}

Buffer::~Buffer()
{
// // if(this -> buffer != NULL)
// {
free(this -> buffer);
// this -> buffer = NULL;
// }
}

void Buffer::reverse(int size)
{
char tmp;
int i;
char * tmpb = this -> buffer;
for(i = 0; i < size / 2; i++)
{
tmp = tmpb[i];
tmpb[i] = tmpb[size - i - 1];
// printf("exchange %x with %x\n", tmp & 0xff, tmpb[i] & 0xff);

tmpb[size - i - 1] = tmp;
}
}

文件.h:

#ifndef __FILE_H__
#define __FILE_H__

#include "Buffer.h"
#include "Exception.h"
#include <stdio.h>
#include <cerrno>

class File
{

private:
FILE * f;
File(const Buffer &);
File& operator=(const File &);



public:
int whence;
// Note: opening the same file twice for writing ("w")
// at the same time is forbidden
File(const char* name, const char *mode);
~File();

int read(Buffer& buffer, int size);
void write(Buffer& buffer, int size);
void seek(int pos);
void close();
// void seek(long offset, int whence);
long size();
};

#endif

文件.cc:

#include "File.h"


File::File(const char* name, const char *mode)
{
f = fopen(name, mode);
if(f == NULL)
throw Exception(errno);
}

File::~File()
{
if(f != NULL)
fclose(f);
}

int File::read(Buffer& buffer, int size)
{
clearerr(this -> f);
size_t tmp;
tmp = fread(buffer.buffer, 1, size, this -> f);

// printf("%ld bytes read\n", tmp);
// for(int i = 0; i < tmp; i++)
// printf("%x ", buffer.buffer[i] & 0xff);
// printf("\n");

if(feof(this -> f) != 0)
return EOF;
if(ferror(this -> f) != 0)
throw Exception(errno);

return tmp;
}

void File::write(Buffer& buffer, int size)
{
size_t tmp;
clearerr(this -> f);
tmp = fwrite(buffer.buffer, 1, size, this -> f);

// printf("%ld bytes written\n", tmp);
// for(int i = 0; i < tmp; i++)
// printf("%x ", buffer.buffer[i] & 0xff);
// printf("\n");

if(ferror(this -> f) != 0)
throw Exception(errno);
}

void File::seek(int pos)
{
int ret = fseek(this -> f, pos, this -> whence);
if(ret != 0)
throw Exception(errno);
}

void File::close()
{
int tmp;
if(this -> f != NULL)
tmp = fclose(this -> f);
this -> f = NULL;
if(tmp != 0)
throw Exception(errno);
}

long File::size()
{
if(fseek(this -> f, 0, SEEK_END) != 0)
throw Exception(errno);

long tmp = ftell(this -> f);
if(tmp == -1)
throw Exception(errno);

if(fseek(this -> f, 0, SEEK_SET) != 0)
throw Exception(errno);
return tmp;
}

注意:我必须使用 C 风格的代码。否则我将无法通过服务器测试。这是一个硬性要求。好吧,您可能认为这个要求很愚蠢。但这是要求。也许有一点是在有人混合使用 C 和 C++ 时学习坏处。

服务器提供了一个主要功能来测试我的实现。只需使用 make 进行编译。结果是一个名为 rcopy 的程序,它逐字节反转文件内容,然后输出到新文件。

这里是详细的错误输出:

make: Entering directory `/home/vmcheck/testhome/co/rcopy'
g++ -c rcopy.cc
g++ -c Buffer.cc
g++ -c Exception.cc
g++ -c File.cc
g++ rcopy.o Buffer.o Exception.o File.o -o rcopy
make: Leaving directory `/home/vmcheck/testhome/co/rcopy'
======== COMPILING AGAINST OUR TESTS ========
g++ -c -Wall -I./ t1.cc -ot1.o
g++ -ot1 t1.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t2.cc -ot2.o
g++ -ot2 t2.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t3.cc -ot3.o
g++ -ot3 t3.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t4.cc -ot4.o
g++ -ot4 t4.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t5.cc -ot5.o
g++ -ot5 t5.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t6.cc -ot6.o
g++ -ot6 t6.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ t7.cc -ot7.o
g++ -ot7 t7.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ f1.cc -of1.o
gcc failed_read.c -ldl -shared -fPIC -o failed_read.so
gcc failed_write.c -ldl -shared -fPIC -o failed_write.so
failed_write.c:5:7: warning: conflicting types for built-in function ‘fwrite’ [enabled by default]
g++ -of1 f1.o Buffer.o Exception.o File.o
g++ -c -Wall -I./ f2.cc -of2.o
g++ -of2 f2.o Buffer.o Exception.o File.o

========= TESTING RCOPY ==========
Run: large file
size of input file: 16473
Run: small file
size of input file: 0

========= TESTING EXCEPTION BEHAVIOUR ==========
*** Test 1 ***
*** Test 2 ***
*** Test 3 ***
bash: line 1: 22041 Segmentation fault ./t3
FAILED

bash 脚本不是段错误的来源。我可以证实这一点。注意到测试服务可以提供许多不同版本的 buggy main 来测试 FileBufferException

最佳答案

当使用无效参数调用时,readwrite 方法可能会导致崩溃。例如,可以使用大小为 10 的缓冲区调用 read,但请求函数 read 读取 20 个字节。在这种情况下,您的缓冲区将溢出。

您有两个解决方案:要么更改缓冲区类以动态调整大小,要么读取/写入缓冲区的最大大小,例如:

tmp = fread(buffer.buffer, 1, min(size, buffer.size), this -> f);

write 也是如此。

关于c++ - 在类 File 和 Buffer 中查找段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40634551/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com