为什么从 class 调用 printf 时会出现分段错误?
Why there is a segmentation fault when calling printf from a class?
这是我的源代码的相关部分(我认为)
#include <iostream>
#include <cstdarg>
#include <cstring>
#include <cstdlib>
class Poly
{
private:
double *coefficients;
size_t degree;
inline double *cfp(size_t i);
public:
Poly();
Poly(size_t n, ...);
void Print() const;
~Poly();
};
Poly::Poly()
{
this->degree = 0;
this->coefficients = new double(1);
*(this->coefficients) = 1.;
}
Poly::Poly(size_t n, ...)
{
va_list coefs;
va_start(coefs, n);
this->degree = n;
n++;
register double *cfs = new double(n);
this->coefficients = cfs;
while (n--)
{
*cfs = va_arg(coefs, double);
cfs++;
}
va_end(coefs);
}
void Poly::Print() const
{
bool started = false;
double c = this->cf(0);
putchar('a');
std::cout << this->degree << '\n';
if (c != 0.)
{
std::cout << c;
started = true;
}
size_t N = this->degree;
for (size_t i = 1; i <= N; i++)
{
c = this->cf(i);
if (c != 0.)
{
if (!started)
started = true;
else
std::cout << ((c < 0.) ? " - " : " + ");
//printf(" + ");
std::cout << fabs(c) << " x^" << i;
//printf("%lf x^%lu", c, i);
}
}
printf("\n");
}
Poly::~Poly()
{
delete this->coefficients;
}
int main()
{
//printf("\n"); <- Uncommenting this line stops the error
Poly p1(7, 1., 3., -9., 2., 0., 8., -2., 6.);
p1.Print();
}
现在,Print
方法有很多 printf
和 cout
。但是,当我取消注释来自 main
的行时,malloc
在第一个 print
或 cout
甚至 putchar
中从“打印”方法中带来分段错误。我在那里找不到任何内存泄漏。为什么会发生以及如何预防?
我在 WSL Ubuntu 上使用 gcc (g++) 9.3.0。该程序使用标志 -lc -g
.
编译
gdb
给我看了这个
malloc(): corrupted top size
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) backtrace
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff7c0f859 in __GI_abort () at abort.c:79
#2 0x00007ffff7c7a3ee in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7da4285 "%s\n")
at ../sysdeps/posix/libc_fatal.c:155
#3 0x00007ffff7c8247c in malloc_printerr (str=str@entry=0x7ffff7da2556 "malloc(): corrupted top size") at malloc.c:5347
#4 0x00007ffff7c8583a in _int_malloc (av=av@entry=0x7ffff7dd5b80 <main_arena>, bytes=bytes@entry=1024) at malloc.c:4107
#5 0x00007ffff7c872d4 in __GI___libc_malloc (bytes=1024) at malloc.c:3058
#6 0x00007ffff7c6ee84 in __GI__IO_file_doallocate (fp=0x7ffff7dd66a0 <_IO_2_1_stdout_>) at filedoalloc.c:101
#7 0x00007ffff7c7f050 in __GI__IO_doallocbuf (fp=fp@entry=0x7ffff7dd66a0 <_IO_2_1_stdout_>) at libioP.h:948
#8 0x00007ffff7c7e0b0 in _IO_new_file_overflow (f=0x7ffff7dd66a0 <_IO_2_1_stdout_>, ch=97) at fileops.c:745
--Type <RET> for more, q to quit, c to continue without paging--
#9 0x00007ffff7c73482 in putchar (c=97) at putchar.c:28
#10 0x0000555555555cfe in Poly::Print (this=0x7fffffffdb90) at polynomial_r.cpp:241
#11 0x0000555555555fd2 in main () at test.cpp:7
(gdb) info frame
Stack level 0, frame at 0x7fffffffd6f0:
rip = 0x7ffff7c3018b in __GI_raise (../sysdeps/unix/sysv/linux/raise.c:50); saved rip = 0x7ffff7c0f859
called by frame at 0x7fffffffd820
source language c.
Arglist at 0x7fffffffd5c8, args: sig=sig@entry=6
Locals at 0x7fffffffd5c8, Previous frame's sp is 0x7fffffffd6f0
Saved registers:
rip at 0x7fffffffd6e8
(gdb)
看起来您通过写入超过堆分配的末尾破坏了堆。我认为你的问题在这里:
register double *cfs = new double(n);
请注意,上面的代码将单个 double
设置分配给值 n
,而我认为您想要做的是分配 n 个双精度数组。为此,您需要使用方括号而不是圆括号:
register double *cfs = new double[n];
这是我的源代码的相关部分(我认为)
#include <iostream>
#include <cstdarg>
#include <cstring>
#include <cstdlib>
class Poly
{
private:
double *coefficients;
size_t degree;
inline double *cfp(size_t i);
public:
Poly();
Poly(size_t n, ...);
void Print() const;
~Poly();
};
Poly::Poly()
{
this->degree = 0;
this->coefficients = new double(1);
*(this->coefficients) = 1.;
}
Poly::Poly(size_t n, ...)
{
va_list coefs;
va_start(coefs, n);
this->degree = n;
n++;
register double *cfs = new double(n);
this->coefficients = cfs;
while (n--)
{
*cfs = va_arg(coefs, double);
cfs++;
}
va_end(coefs);
}
void Poly::Print() const
{
bool started = false;
double c = this->cf(0);
putchar('a');
std::cout << this->degree << '\n';
if (c != 0.)
{
std::cout << c;
started = true;
}
size_t N = this->degree;
for (size_t i = 1; i <= N; i++)
{
c = this->cf(i);
if (c != 0.)
{
if (!started)
started = true;
else
std::cout << ((c < 0.) ? " - " : " + ");
//printf(" + ");
std::cout << fabs(c) << " x^" << i;
//printf("%lf x^%lu", c, i);
}
}
printf("\n");
}
Poly::~Poly()
{
delete this->coefficients;
}
int main()
{
//printf("\n"); <- Uncommenting this line stops the error
Poly p1(7, 1., 3., -9., 2., 0., 8., -2., 6.);
p1.Print();
}
现在,Print
方法有很多 printf
和 cout
。但是,当我取消注释来自 main
的行时,malloc
在第一个 print
或 cout
甚至 putchar
中从“打印”方法中带来分段错误。我在那里找不到任何内存泄漏。为什么会发生以及如何预防?
我在 WSL Ubuntu 上使用 gcc (g++) 9.3.0。该程序使用标志 -lc -g
.
gdb
给我看了这个
malloc(): corrupted top size
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) backtrace
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff7c0f859 in __GI_abort () at abort.c:79
#2 0x00007ffff7c7a3ee in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7da4285 "%s\n")
at ../sysdeps/posix/libc_fatal.c:155
#3 0x00007ffff7c8247c in malloc_printerr (str=str@entry=0x7ffff7da2556 "malloc(): corrupted top size") at malloc.c:5347
#4 0x00007ffff7c8583a in _int_malloc (av=av@entry=0x7ffff7dd5b80 <main_arena>, bytes=bytes@entry=1024) at malloc.c:4107
#5 0x00007ffff7c872d4 in __GI___libc_malloc (bytes=1024) at malloc.c:3058
#6 0x00007ffff7c6ee84 in __GI__IO_file_doallocate (fp=0x7ffff7dd66a0 <_IO_2_1_stdout_>) at filedoalloc.c:101
#7 0x00007ffff7c7f050 in __GI__IO_doallocbuf (fp=fp@entry=0x7ffff7dd66a0 <_IO_2_1_stdout_>) at libioP.h:948
#8 0x00007ffff7c7e0b0 in _IO_new_file_overflow (f=0x7ffff7dd66a0 <_IO_2_1_stdout_>, ch=97) at fileops.c:745
--Type <RET> for more, q to quit, c to continue without paging--
#9 0x00007ffff7c73482 in putchar (c=97) at putchar.c:28
#10 0x0000555555555cfe in Poly::Print (this=0x7fffffffdb90) at polynomial_r.cpp:241
#11 0x0000555555555fd2 in main () at test.cpp:7
(gdb) info frame
Stack level 0, frame at 0x7fffffffd6f0:
rip = 0x7ffff7c3018b in __GI_raise (../sysdeps/unix/sysv/linux/raise.c:50); saved rip = 0x7ffff7c0f859
called by frame at 0x7fffffffd820
source language c.
Arglist at 0x7fffffffd5c8, args: sig=sig@entry=6
Locals at 0x7fffffffd5c8, Previous frame's sp is 0x7fffffffd6f0
Saved registers:
rip at 0x7fffffffd6e8
(gdb)
看起来您通过写入超过堆分配的末尾破坏了堆。我认为你的问题在这里:
register double *cfs = new double(n);
请注意,上面的代码将单个 double
设置分配给值 n
,而我认为您想要做的是分配 n 个双精度数组。为此,您需要使用方括号而不是圆括号:
register double *cfs = new double[n];