[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

realloc_failed

qqqqqq wwwwww

3/29/2011 8:22:00 PM

Hi, my name is Ivanov Roman. Can you give me any advice: realloc has
failed in the function Add?

///////////////// DynamicArray.h /////////////////////////////
#ifndef _DYNAMICARRAY_H
#define _DYNAMICARRAY_H

#include <stdlib.h>
#include <assert.h>
#include <string.h>

struct iterator;

struct iterator_ops {
void * (* GetData) (struct iterator * this);
int (* Delete) (struct iterator * this);
};

struct iterator * alloc_iter (void * data, size_t size);

struct dyn_array;

struct array_ops {
int (* Add) (struct dyn_array * this, void * data, size_t size);
int (* Del) (struct dyn_array * this, int position);
int (* DeleteArray) (struct dyn_array * this);
void * (* Get) (struct dyn_array * this, int n);
struct iterator * (* Search) (const void * key,
const struct dyn_array * this);
struct iterator * (* GetBegin) (struct dyn_array * this);
int (* cmp) (const void * A, const void * B);
int (* cmp_content) (const void * A, const void * B);
int (* SetCompare) (struct dyn_array * this,
int (* cmp_user) (const void * A, const void * B));
};

struct dyn_array * alloc_array (int (* cmp_content) (const void * A,
const void * B));

#endif // _DYNAMICARRAY_H

////////////////////// DynamicArray.c ///////////////////////////
#include <stdio.h>

#include "DynamicArray.h"

struct iterator {
void * data;
size_t size;
struct iterator_ops * ops;
struct dyn_array * owner;
};

void * GetData (struct iterator * this) {
if (this == NULL)
return NULL;
return this->data;
}

int Delete (struct iterator * this) {
if (this == NULL)
return -1;

if (this->data)
free(this->data);

free(this);
return 0;
}

struct iterator * alloc_iter (void * data, size_t size) {
/*if (size < 1)
return NULL;*/

struct iterator * result = (struct iterator *)malloc(sizeof(struct
iterator));
if (result == (struct iterator *)NULL)
return NULL;

result->owner = NULL;
result->data = data;
result->size = size;
result->ops = (struct iterator_ops*)malloc(sizeof(struct
iterator_ops));

if (result->ops == NULL) {
free(result);
return NULL;
}

result->ops->GetData = GetData;
result->ops->Delete = Delete;
return result;
};

struct dyn_array {
struct iterator * begin;
struct array_ops * ops;
int count_total;
int count_filled;
};

int SetCompare (struct dyn_array * this, int (* cmp_user) (const void
* A,
const void * B)) {
if (this == NULL)
return -1;
if (cmp_user == NULL)
return -1;

this->ops->cmp_content = cmp_user;
return 0;
}

int cmp (const void * A, const void * B) {
assert(A != NULL && B != NULL);
assert(((struct iterator *)A)->ops != NULL &&
((struct iterator *)B)->ops != NULL);
assert(((struct iterator *)A)->data != NULL &&
((struct iterator *)B)->data != NULL);
assert(((struct iterator *)A)->owner != NULL &&
((struct iterator *)B)->owner != NULL);
assert(((struct iterator *)A)->owner == ((struct iterator *)B)-
>owner);
if (((struct iterator *)A)->owner->begin == A && (((struct
iterator *)A)->owner->ops->cmp_content(((struct iterator *)A)->data,
((struct iterator *)B)->data) > 0)) {
printf("Begin moved\n");
((struct iterator *)A)->owner->begin = (struct iterator *)B;
}

if (((struct iterator *)B)->owner->begin == B && (((struct
iterator *)A)->owner->ops->cmp_content(((struct iterator *)A)->data,
((struct iterator *)B)->data) < 0)) {
printf("Begin moved\n");
((struct iterator *)B)->owner->begin = (struct iterator *)A;
}
return ((struct iterator *)A)->owner->ops->cmp_content(((struct
iterator *)A)->data,
((struct iterator *)B)->data);
}

int Add (struct dyn_array * this, void * data, size_t size) {
if (this == NULL)
return -1;

if (size < 1)
return -1;

if (this->count_total == 0) {
printf("97: Head added\n");
struct iterator * i = alloc_iter(data, size);
if (i == NULL)
return -1;
i->owner = this;
this->begin = i;
this->count_total = 1;
this->count_filled = 1;
return 0;

} else {

if (this->begin == NULL) {
printf("111\n");
return -1;
}
if (this->count_filled == this->count_total) {
struct iterator * buf = this->begin;

printf("112: realloc size = %d\n", sizeof(struct iterator
*) * this->count_total * 2);

this->begin = realloc(this->begin,
sizeof(struct iterator *) * this->count_total * 2 +
1);

printf("119: reallocated sucessfuly\n");
if (this->begin == NULL) {
this->begin = buf;
return -1;
}
this->count_total *=2;
}
}
struct iterator * i = alloc_iter(data, size);
if (i == NULL) {
return -1;
}
i->owner = this;
*(this->begin + this->count_filled) = *i;
free(i);
qsort(this->begin, this->count_filled, this->begin->size, this-
>ops->cmp);

this->count_filled++;

return 0;
}

int Del (struct dyn_array * this, int position) {
if (this == NULL)
return -1;

if (position > this->count_filled)
return -1;

free(this->begin + position);

memmove(this->begin + position, this->begin + position + 1,
this->count_filled - position);
return 0;
}

int DeleteArray (struct dyn_array * this) {
if (this == NULL)
return -1;

if (this->begin == NULL) {
free(this->ops);
free(this);
return 0;
}

int position = 0;
for (; position < this->count_filled; position ++)
(this->begin + position)->ops->Delete(this->begin + position);

free (this->ops);
free (this);
return 0;
}

void * Get (struct dyn_array * this, int n) {
if (this == NULL)
return NULL;

if (n > this->count_filled)
return NULL;

if ((this->begin + n) == NULL)
return NULL;

return (this->begin + n)->ops->GetData(this->begin + n);
}

struct iterator * Search (const void * key, const struct dyn_array *
this) {
return bsearch(key, this->begin, this->count_filled, this->begin-
>size, this->ops->cmp);
}

struct iterator * GetBegin (struct dyn_array * this) {
if (this == NULL)
return NULL;
return this->begin;
}

struct dyn_array * alloc_array (int (* cmp_content) (const void * A,
const void * B)) {
if (cmp_content == NULL)
return NULL;

struct dyn_array * result = (struct dyn_array
*)malloc(sizeof(struct dyn_array));

result->begin = NULL;
result->ops = (struct array_ops *)malloc(sizeof(struct
array_ops));

if (result->ops == NULL) {
free(result);
return NULL;
}
result->ops->Add = Add;
result->ops->Del = Del;
result->ops->DeleteArray = DeleteArray;
result->ops->Get = Get;
result->ops->GetBegin = GetBegin;
result->ops->Search = Search;
result->ops->SetCompare = SetCompare;
result->ops->cmp = cmp;
result->ops->cmp_content = cmp_content;

return result;
}
/////////////////// DynArray_unittest.c //////////////////////
#include "DynamicArray.h"
#include <stdio.h>

int cmpInt (const void * a, const void * b){
return ( *(int *)a - *(int *)b );
}

int main() {

////// Stage 1 //////
printf("/// Stage 1 ///\n");
// alloc_arrayint ((* cmp_content) (const void * A, const void *
B))
struct dyn_array * arrayInt;

arrayInt = alloc_array(NULL);
if (arrayInt == NULL)
printf("alloc_array returned NULL\n");

arrayInt = alloc_array(cmpInt);
printf("arrayInt = %x\n", arrayInt);

// int DeleteArray (struct dyn_array * this)
if (DeleteArray(NULL) == -1)
printf("DeleteArray returned NULL\n");

if (DeleteArray(arrayInt) == 0)
printf("DeleteArray executed 1\n");

////// Stage 2 //////
printf("/// Stage 2 ///\n");

arrayInt = alloc_array(cmpInt);
printf("arrayInt = %x\n", arrayInt);

// int Add (struct dyn_array * this, void * data, size_t size)
int dataInt = 0;
if (Add(NULL, &dataInt, sizeof(int)) == -1)
printf("Add returned NULL\n");

if (Add(arrayInt, &dataInt, 0) == -1)
printf("Add returned NULL\n");

dataInt = 7;
if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
printf("Add added 7\n");
dataInt = 2;
if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
printf("Add added 2\n");
dataInt = 45;
if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
printf("Add added 45\n");
dataInt = 78;
if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
printf("Add added 78\n");
dataInt = 25;
if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
printf("Add added 25\n");

if (DeleteArray(arrayInt) == 0)
printf("DeleteArray executed successfully 1\n");

return (EXIT_SUCCESS);
}

////////////////////// strace list ///////////////////////////
execve("./unittest", ["./unittest"], [/* 38 vars */]) = 0
brk(0) = 0x1c77000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or
directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x7f85373ae000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=118236, ...}) = 0
mmap(NULL, 118236, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8537391000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or
directory)
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`
\355\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1572232, ...}) = 0
mmap(NULL, 3680296, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3,
0) = 0x7f8536e0e000
mprotect(0x7f8536f88000, 2093056, PROT_NONE) = 0
mmap(0x7f8537187000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|
MAP_FIXED|MAP_DENYWRITE, 3, 0x179000) = 0x7f8537187000
mmap(0x7f853718c000, 18472, PROT_READ|PROT_WRITE, MAP_PRIVATE|
MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f853718c000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x7f8537390000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x7f853738f000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x7f853738e000
arch_prctl(ARCH_SET_FS, 0x7f853738f700) = 0
mprotect(0x7f8537187000, 16384, PROT_READ) = 0
mprotect(0x601000, 4096, PROT_READ) = 0
mprotect(0x7f85373b0000, 4096, PROT_READ) = 0
munmap(0x7f8537391000, 118236) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x7f85373ad000
write(1, "/// Stage 1 ///\n", 16/// Stage 1 ///
) = 16
write(1, "alloc_array returned NULL\n", 26alloc_array returned NULL
) = 26
brk(0) = 0x1c77000
brk(0x1c98000) = 0x1c98000
write(1, "arrayInt = 1c77010\n", 19arrayInt = 1c77010
) = 19
write(1, "DeleteArray returned NULL\n", 26DeleteArray returned NULL
) = 26
write(1, "DeleteArray executed 1\n", 23DeleteArray executed 1
) = 23
write(1, "/// Stage 2 ///\n", 16/// Stage 2 ///
) = 16
write(1, "arrayInt = 1c77010\n", 19arrayInt = 1c77010
) = 19
write(1, "Add returned NULL\n", 18Add returned NULL
) = 18
write(1, "Add returned NULL\n", 18Add returned NULL
) = 18
write(1, "97: Head added\n", 1597: Head added
) = 15
write(1, "Add added 7\n", 12Add added 7
) = 12
write(1, "112: realloc size = 16\n", 23112: realloc size = 16
) = 23
write(1, "119: reallocated sucessfuly\n", 28119: reallocated
sucessfuly
) = 28
write(1, "Add added 2\n", 12Add added 2
) = 12
write(1, "112: realloc size = 32\n", 23112: realloc size = 32
) = 23
open("/dev/tty", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
writev(3, [{"*** glibc detected *** ", 23}, {"./unittest", 10}, {": ",
2}, {"realloc(): invalid next size", 28}, {": 0x", 4},
{"0000000001c77080", 16}, {" ***\n", 5}], 7*** glibc detected *** ./
unittest: realloc(): invalid next size: 0x0000000001c77080 ***
) = 88
mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|
MAP_NORESERVE, -1, 0) = 0x7f852ee0e000
munmap(0x7f852ee0e000, 18817024) = 0
munmap(0x7f8534000000, 48291840) = 0
mprotect(0x7f8530000000, 135168, PROT_READ|PROT_WRITE) = 0
open("/etc/ld.so.cache", O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=118236, ...}) = 0
mmap(NULL, 118236, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7f8537371000
close(4) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or
directory)
open("/lib/libgcc_s.so.1", O_RDONLY) = 4
read(4, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200-
\0\0\0\0\0\0"..., 832) = 832
fstat(4, {st_mode=S_IFREG|0644, st_size=92552, ...}) = 0
mmap(NULL, 2188280, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4,
0) = 0x7f8536bf7000
mprotect(0x7f8536c0d000, 2093056, PROT_NONE) = 0
mmap(0x7f8536e0c000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|
MAP_DENYWRITE, 4, 0x15000) = 0x7f8536e0c000
close(4) = 0
mprotect(0x7f8536e0c000, 4096, PROT_READ) = 0
munmap(0x7f8537371000, 118236) = 0
write(3, "======= Backtrace: =========\n", 29======= Backtrace:
=========
) = 29
writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"+0x", 3}, {"775b6", 5},
{")", 1}, {"[0x", 3}, {"7f8536e855b6", 12}, {"]\n", 2}], 8/lib/libc.so.
6(+0x775b6)[0x7f8536e855b6]
) = 41
writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"+0x", 3}, {"7dd96", 5},
{")", 1}, {"[0x", 3}, {"7f8536e8bd96", 12}, {"]\n", 2}], 8/lib/libc.so.
6(+0x7dd96)[0x7f8536e8bd96]
) = 41
writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"realloc", 7}, {"+0x",
3}, {"f0", 2}, {")", 1}, {"[0x", 3}, {"7f8536e8c0b0", 12}, {"]\n",
2}], 9/lib/libc.so.6(realloc+0xf0)[0x7f8536e8c0b0]
) = 45
writev(3, [{"./unittest", 10}, {"[0x", 3}, {"400be3", 6}, {"]\n", 2}],
4./unittest[0x400be3]
) = 21
writev(3, [{"./unittest", 10}, {"[0x", 3}, {"401217", 6}, {"]\n", 2}],
4./unittest[0x401217]
) = 21
writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"__libc_start_main",
17}, {"+0x", 3}, {"fd", 2}, {")", 1}, {"[0x", 3}, {"7f8536e2cc4d",
12}, {"]\n", 2}], 9/lib/libc.so.6(__libc_start_main+0xfd)
[0x7f8536e2cc4d]
) = 55
writev(3, [{"./unittest", 10}, {"[0x", 3}, {"4006d9", 6}, {"]\n", 2}],
4./unittest[0x4006d9]
) = 21
write(3, "======= Memory map: ========\n", 29======= Memory map:
========
) = 29
open("/proc/self/maps", O_RDONLY) = 4
read(4, "00400000-00402000 r-xp 00000000 "..., 1024) = 1024
write(3, "00400000-00402000 r-xp 00000000 "..., 102400400000-00402000
r-xp 00000000 08:07 785378 /home/iroman/
Desktop/Project/DynamicArray/unittest
00601000-00602000 r--p 00001000 08:07
785378 /home/iroman/Desktop/Project/
DynamicArray/unittest
00602000-00603000 rw-p 00002000 08:07
785378 /home/iroman/Desktop/Project/
DynamicArray/unittest
01c77000-01c98000 rw-p 00000000 00:00
0 [heap]
7f8530000000-7f8530021000 rw-p 00000000 00:00 0
7f8530021000-7f8534000000 ---p 00000000 00:00 0
7f8536bf7000-7f8536c0d000 r-xp 00000000 08:06
2645 /lib/libgcc_s.so.1
7f8536c0d000-7f8536e0c000 ---p 00016000 08:06
2645 /lib/libgcc_s.so.1
7f8536e0c000-7f8536e0d000 r--p 00015000 08:06
2645 /lib/libgcc_s.so.1
7f8536e0d000-7f8536e0e000 rw-p 00016000 08:06
2645 /lib/libgcc_s.so.1
7f8536e0e000-7f8536f88000 r-xp 00000000 08:06
8050 /lib/libc-2.11.1.so
7f8536f88000-) = 1024
read(4, "7f8537187000 ---p 0017a000 08:06"..., 1024) = 980
write(3, "7f8537187000 ---p 0017a000 08:06"..., 9807f8537187000 ---p
0017a000 08:06 8050 /lib/libc-2.11.1.so
7f8537187000-7f853718b000 r--p 00179000 08:06
8050 /lib/libc-2.11.1.so
7f853718b000-7f853718c000 rw-p 0017d000 08:06
8050 /lib/libc-2.11.1.so
7f853718c000-7f8537191000 rw-p 00000000 00:00 0
7f8537191000-7f85371b1000 r-xp 00000000 08:06
7967 /lib/ld-2.11.1.so
7f853738e000-7f8537391000 rw-p 00000000 00:00 0
7f85373ad000-7f85373b0000 rw-p 00000000 00:00 0
7f85373b0000-7f85373b1000 r--p 0001f000 08:06
7967 /lib/ld-2.11.1.so
7f85373b1000-7f85373b2000 rw-p 00020000 08:06
7967 /lib/ld-2.11.1.so
7f85373b2000-7f85373b3000 rw-p 00000000 00:00 0
7fffc20b5000-7fffc20ca000 rw-p 00000000 00:00
0 [stack]
7fffc21ff000-7fffc2200000 r-xp 00000000 00:00
0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00
0 [vsyscall]
) = 980
read(4, "", 1024) = 0
close(4) = 0
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
gettid() = 4334
tgkill(4334, 4334, SIGABRT) = 0
--- SIGABRT (Aborted) @ 0 (0) ---
+++ killed by SIGABRT +++
Emergency Stop
//////////////////////////// valgrind list ////////////////////////
==4380== Memcheck, a memory error detector
==4380== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et
al.
==4380== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for
copyright info
==4380== Command: ./unittest
==4380==
/// Stage 1 ///
alloc_array returned NULL
arrayInt = 51b0040
DeleteArray returned NULL
DeleteArray executed 1
/// Stage 2 ///
arrayInt = 51b0130
Add returned NULL
Add returned NULL
==4380== Conditional jump or move depends on uninitialised value(s)
==4380== at 0x400AEF: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4011B2: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380==
97: Head added
Add added 7
112: realloc size = 16
119: reallocated sucessfuly
==4380== Invalid write of size 8
==4380== at 0x400C7B: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b02f0 is 15 bytes after a block of size 17
alloc'd
==4380== at 0x4C275A2: realloc (vg_replace_malloc.c:525)
==4380== by 0x400BE2: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380==
==4380== Invalid write of size 8
==4380== at 0x400C82: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b02f8 is not stack'd, malloc'd or (recently)
free'd
==4380==
==4380== Invalid write of size 8
==4380== at 0x400C8A: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b0300 is not stack'd, malloc'd or (recently)
free'd
==4380==
==4380== Invalid write of size 8
==4380== at 0x400C92: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b0308 is not stack'd, malloc'd or (recently)
free'd
==4380==
Add added 2
112: realloc size = 32
119: reallocated sucessfuly
==4380== Invalid write of size 8
==4380== at 0x400C7B: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b0420 is not stack'd, malloc'd or (recently)
free'd
==4380==
==4380== Invalid write of size 8
==4380== at 0x400C82: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b0428 is not stack'd, malloc'd or (recently)
free'd
==4380==
==4380== Invalid write of size 8
==4380== at 0x400C8A: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b0430 is not stack'd, malloc'd or (recently)
free'd
==4380==
==4380== Invalid write of size 8
==4380== at 0x400C92: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== Address 0x51b0438 is not stack'd, malloc'd or (recently)
free'd
==4380==
==4380== Conditional jump or move depends on uninitialised value(s)
==4380== at 0x400925: cmp (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4E650FA: msort_with_tmp (msort.c:65)
==4380== by 0x4E656EB: qsort_r (msort.c:294)
==4380== by 0x400CD4: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380==
==4380== Conditional jump or move depends on uninitialised value(s)
==4380== at 0x400932: cmp (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x4E650FA: msort_with_tmp (msort.c:65)
==4380== by 0x4E656EB: qsort_r (msort.c:294)
==4380== by 0x400CD4: Add (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
DynamicArray/unittest)
==4380==
unittest: DynamicArray.c:79: cmp: Assertion `((struct iterator *)A)-
>ops != ((void *)0) && ((struct iterator *)B)->ops != ((void *)0)'
failed.
==4380==
==4380== HEAP SUMMARY:
==4380== in use at exit: 321 bytes in 7 blocks
==4380== total heap usage: 15 allocs, 8 frees, 930 bytes allocated
==4380==
==4380== LEAK SUMMARY:
==4380== definitely lost: 48 bytes in 3 blocks
==4380== indirectly lost: 0 bytes in 0 blocks
==4380== possibly lost: 0 bytes in 0 blocks
==4380== still reachable: 273 bytes in 4 blocks
==4380== suppressed: 0 bytes in 0 blocks
==4380== Rerun with --leak-check=full to see details of leaked memory
==4380==
==4380== For counts of detected and suppressed errors, rerun with: -v
==4380== Use --track-origins=yes to see where uninitialised values
come from
==4380== ERROR SUMMARY: 11 errors from 11 contexts (suppressed: 4 from
4)
Emergency Stop

thanks

13 Answers

gordonb.xwohw

3/29/2011 11:01:00 PM

0

> Hi, my name is Ivanov Roman. Can you give me any advice: realloc has
> failed in the function Add?

How can you TELL realloc() has failed? It prints "119: reallocated
successfully"? That's a rather strange message which is printed
whether realloc() fails or not.

It appears that your code is scribbling on memory it doesn't own.
Fix that. It can cause malloc() and realloc() to malfunction.



>
> ///////////////// DynamicArray.h /////////////////////////////
> #ifndef _DYNAMICARRAY_H
> #define _DYNAMICARRAY_H
>
> #include <stdlib.h>
> #include <assert.h>
> #include <string.h>
>
> struct iterator;
>
> struct iterator_ops {
> void * (* GetData) (struct iterator * this);
> int (* Delete) (struct iterator * this);
> };
>
> struct iterator * alloc_iter (void * data, size_t size);
>
> struct dyn_array;
>
> struct array_ops {
> int (* Add) (struct dyn_array * this, void * data, size_t size);
> int (* Del) (struct dyn_array * this, int position);
> int (* DeleteArray) (struct dyn_array * this);
> void * (* Get) (struct dyn_array * this, int n);
> struct iterator * (* Search) (const void * key,
> const struct dyn_array * this);
> struct iterator * (* GetBegin) (struct dyn_array * this);
> int (* cmp) (const void * A, const void * B);
> int (* cmp_content) (const void * A, const void * B);
> int (* SetCompare) (struct dyn_array * this,
> int (* cmp_user) (const void * A, const void * B));
> };
>
> struct dyn_array * alloc_array (int (* cmp_content) (const void * A,
> const void * B));
>
> #endif // _DYNAMICARRAY_H
>
> ////////////////////// DynamicArray.c ///////////////////////////
> #include <stdio.h>
>
> #include "DynamicArray.h"
>
> struct iterator {
> void * data;
> size_t size;
> struct iterator_ops * ops;
> struct dyn_array * owner;
> };
>
> void * GetData (struct iterator * this) {
> if (this == NULL)
> return NULL;
> return this->data;
> }
>
> int Delete (struct iterator * this) {
> if (this == NULL)
> return -1;
>
> if (this->data)
> free(this->data);
>
> free(this);
> return 0;
> }
>
> struct iterator * alloc_iter (void * data, size_t size) {
> /*if (size < 1)
> return NULL;*/
>
> struct iterator * result = (struct iterator *)malloc(sizeof(struct
> iterator));
> if (result == (struct iterator *)NULL)
> return NULL;
>
> result->owner = NULL;
> result->data = data;
> result->size = size;
> result->ops = (struct iterator_ops*)malloc(sizeof(struct
> iterator_ops));
>
> if (result->ops == NULL) {
> free(result);
> return NULL;
> }
>
> result->ops->GetData = GetData;
> result->ops->Delete = Delete;
> return result;
> };
>
> struct dyn_array {
> struct iterator * begin;
> struct array_ops * ops;
> int count_total;
> int count_filled;
> };
>
> int SetCompare (struct dyn_array * this, int (* cmp_user) (const void
> * A,
> const void * B)) {
> if (this == NULL)
> return -1;
> if (cmp_user == NULL)
> return -1;
>
> this->ops->cmp_content = cmp_user;
> return 0;
> }
>
> int cmp (const void * A, const void * B) {
> assert(A != NULL && B != NULL);
> assert(((struct iterator *)A)->ops != NULL &&
> ((struct iterator *)B)->ops != NULL);
> assert(((struct iterator *)A)->data != NULL &&
> ((struct iterator *)B)->data != NULL);
> assert(((struct iterator *)A)->owner != NULL &&
> ((struct iterator *)B)->owner != NULL);
> assert(((struct iterator *)A)->owner == ((struct iterator *)B)-
>>owner);
> if (((struct iterator *)A)->owner->begin == A && (((struct
> iterator *)A)->owner->ops->cmp_content(((struct iterator *)A)->data,
> ((struct iterator *)B)->data) > 0)) {
> printf("Begin moved\n");
> ((struct iterator *)A)->owner->begin = (struct iterator *)B;
> }
>
> if (((struct iterator *)B)->owner->begin == B && (((struct
> iterator *)A)->owner->ops->cmp_content(((struct iterator *)A)->data,
> ((struct iterator *)B)->data) < 0)) {
> printf("Begin moved\n");
> ((struct iterator *)B)->owner->begin = (struct iterator *)A;
> }
> return ((struct iterator *)A)->owner->ops->cmp_content(((struct
> iterator *)A)->data,
> ((struct iterator *)B)->data);
> }
>
> int Add (struct dyn_array * this, void * data, size_t size) {
> if (this == NULL)
> return -1;
>
> if (size < 1)
> return -1;
>
> if (this->count_total == 0) {
> printf("97: Head added\n");
> struct iterator * i = alloc_iter(data, size);
> if (i == NULL)
> return -1;
> i->owner = this;
> this->begin = i;
> this->count_total = 1;
> this->count_filled = 1;
> return 0;
>
> } else {
>
> if (this->begin == NULL) {
> printf("111\n");
> return -1;
> }
> if (this->count_filled == this->count_total) {
> struct iterator * buf = this->begin;
>
> printf("112: realloc size = %d\n", sizeof(struct iterator
> *) * this->count_total * 2);
>
> this->begin = realloc(this->begin,
> sizeof(struct iterator *) * this->count_total * 2 +
> 1);
>
> printf("119: reallocated sucessfuly\n");
> if (this->begin == NULL) {
> this->begin = buf;
> return -1;
> }
> this->count_total *=2;
> }
> }
> struct iterator * i = alloc_iter(data, size);
> if (i == NULL) {
> return -1;
> }
> i->owner = this;
> *(this->begin + this->count_filled) = *i;
> free(i);
> qsort(this->begin, this->count_filled, this->begin->size, this-
>>ops->cmp);
>
> this->count_filled++;
>
> return 0;
> }
>
> int Del (struct dyn_array * this, int position) {
> if (this == NULL)
> return -1;
>
> if (position > this->count_filled)
> return -1;
>
> free(this->begin + position);
>
> memmove(this->begin + position, this->begin + position + 1,
> this->count_filled - position);
> return 0;
> }
>
> int DeleteArray (struct dyn_array * this) {
> if (this == NULL)
> return -1;
>
> if (this->begin == NULL) {
> free(this->ops);
> free(this);
> return 0;
> }
>
> int position = 0;
> for (; position < this->count_filled; position ++)
> (this->begin + position)->ops->Delete(this->begin + position);
>
> free (this->ops);
> free (this);
> return 0;
> }
>
> void * Get (struct dyn_array * this, int n) {
> if (this == NULL)
> return NULL;
>
> if (n > this->count_filled)
> return NULL;
>
> if ((this->begin + n) == NULL)
> return NULL;
>
> return (this->begin + n)->ops->GetData(this->begin + n);
> }
>
> struct iterator * Search (const void * key, const struct dyn_array *
> this) {
> return bsearch(key, this->begin, this->count_filled, this->begin-
>>size, this->ops->cmp);
> }
>
> struct iterator * GetBegin (struct dyn_array * this) {
> if (this == NULL)
> return NULL;
> return this->begin;
> }
>
> struct dyn_array * alloc_array (int (* cmp_content) (const void * A,
> const void * B)) {
> if (cmp_content == NULL)
> return NULL;
>
> struct dyn_array * result = (struct dyn_array
> *)malloc(sizeof(struct dyn_array));
>
> result->begin = NULL;
> result->ops = (struct array_ops *)malloc(sizeof(struct
> array_ops));
>
> if (result->ops == NULL) {
> free(result);
> return NULL;
> }
> result->ops->Add = Add;
> result->ops->Del = Del;
> result->ops->DeleteArray = DeleteArray;
> result->ops->Get = Get;
> result->ops->GetBegin = GetBegin;
> result->ops->Search = Search;
> result->ops->SetCompare = SetCompare;
> result->ops->cmp = cmp;
> result->ops->cmp_content = cmp_content;
>
> return result;
> }
> /////////////////// DynArray_unittest.c //////////////////////
> #include "DynamicArray.h"
> #include <stdio.h>
>
> int cmpInt (const void * a, const void * b){
> return ( *(int *)a - *(int *)b );
> }
>
> int main() {
>
> ////// Stage 1 //////
> printf("/// Stage 1 ///\n");
> // alloc_arrayint ((* cmp_content) (const void * A, const void *
> B))
> struct dyn_array * arrayInt;
>
> arrayInt = alloc_array(NULL);
> if (arrayInt == NULL)
> printf("alloc_array returned NULL\n");
>
> arrayInt = alloc_array(cmpInt);
> printf("arrayInt = %x\n", arrayInt);
>
> // int DeleteArray (struct dyn_array * this)
> if (DeleteArray(NULL) == -1)
> printf("DeleteArray returned NULL\n");
>
> if (DeleteArray(arrayInt) == 0)
> printf("DeleteArray executed 1\n");
>
> ////// Stage 2 //////
> printf("/// Stage 2 ///\n");
>
> arrayInt = alloc_array(cmpInt);
> printf("arrayInt = %x\n", arrayInt);
>
> // int Add (struct dyn_array * this, void * data, size_t size)
> int dataInt = 0;
> if (Add(NULL, &dataInt, sizeof(int)) == -1)
> printf("Add returned NULL\n");
>
> if (Add(arrayInt, &dataInt, 0) == -1)
> printf("Add returned NULL\n");
>
> dataInt = 7;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 7\n");
> dataInt = 2;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 2\n");
> dataInt = 45;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 45\n");
> dataInt = 78;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 78\n");
> dataInt = 25;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 25\n");
>
> if (DeleteArray(arrayInt) == 0)
> printf("DeleteArray executed successfully 1\n");
>
> return (EXIT_SUCCESS);
> }
>
> ////////////////////// strace list ///////////////////////////
> execve("./unittest", ["./unittest"], [/* 38 vars */]) = 0
> brk(0) = 0x1c77000
> access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or
> directory)
> mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
> 0) = 0x7f85373ae000
> access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or
> directory)
> open("/etc/ld.so.cache", O_RDONLY) = 3
> fstat(3, {st_mode=S_IFREG|0644, st_size=118236, ...}) = 0
> mmap(NULL, 118236, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f8537391000
> close(3) = 0
> access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or
> directory)
> open("/lib/libc.so.6", O_RDONLY) = 3
> read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`
> \355\1\0\0\0\0\0"..., 832) = 832
> fstat(3, {st_mode=S_IFREG|0755, st_size=1572232, ...}) = 0
> mmap(NULL, 3680296, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3,
> 0) = 0x7f8536e0e000
> mprotect(0x7f8536f88000, 2093056, PROT_NONE) = 0
> mmap(0x7f8537187000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|
> MAP_FIXED|MAP_DENYWRITE, 3, 0x179000) = 0x7f8537187000
> mmap(0x7f853718c000, 18472, PROT_READ|PROT_WRITE, MAP_PRIVATE|
> MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f853718c000
> close(3) = 0
> mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
> 0) = 0x7f8537390000
> mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
> 0) = 0x7f853738f000
> mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
> 0) = 0x7f853738e000
> arch_prctl(ARCH_SET_FS, 0x7f853738f700) = 0
> mprotect(0x7f8537187000, 16384, PROT_READ) = 0
> mprotect(0x601000, 4096, PROT_READ) = 0
> mprotect(0x7f85373b0000, 4096, PROT_READ) = 0
> munmap(0x7f8537391000, 118236) = 0
> fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
> mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
> 0) = 0x7f85373ad000
> write(1, "/// Stage 1 ///\n", 16/// Stage 1 ///
> ) = 16
> write(1, "alloc_array returned NULL\n", 26alloc_array returned NULL
> ) = 26
> brk(0) = 0x1c77000
> brk(0x1c98000) = 0x1c98000
> write(1, "arrayInt = 1c77010\n", 19arrayInt = 1c77010
> ) = 19
> write(1, "DeleteArray returned NULL\n", 26DeleteArray returned NULL
> ) = 26
> write(1, "DeleteArray executed 1\n", 23DeleteArray executed 1
> ) = 23
> write(1, "/// Stage 2 ///\n", 16/// Stage 2 ///
> ) = 16
> write(1, "arrayInt = 1c77010\n", 19arrayInt = 1c77010
> ) = 19
> write(1, "Add returned NULL\n", 18Add returned NULL
> ) = 18
> write(1, "Add returned NULL\n", 18Add returned NULL
> ) = 18
> write(1, "97: Head added\n", 1597: Head added
> ) = 15
> write(1, "Add added 7\n", 12Add added 7
> ) = 12
> write(1, "112: realloc size = 16\n", 23112: realloc size = 16
> ) = 23
> write(1, "119: reallocated sucessfuly\n", 28119: reallocated
> sucessfuly
> ) = 28
> write(1, "Add added 2\n", 12Add added 2
> ) = 12
> write(1, "112: realloc size = 32\n", 23112: realloc size = 32
> ) = 23
> open("/dev/tty", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
> writev(3, [{"*** glibc detected *** ", 23}, {"./unittest", 10}, {": ",
> 2}, {"realloc(): invalid next size", 28}, {": 0x", 4},
> {"0000000001c77080", 16}, {" ***\n", 5}], 7*** glibc detected *** ./
> unittest: realloc(): invalid next size: 0x0000000001c77080 ***
> ) = 88
> mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|
> MAP_NORESERVE, -1, 0) = 0x7f852ee0e000
> munmap(0x7f852ee0e000, 18817024) = 0
> munmap(0x7f8534000000, 48291840) = 0
> mprotect(0x7f8530000000, 135168, PROT_READ|PROT_WRITE) = 0
> open("/etc/ld.so.cache", O_RDONLY) = 4
> fstat(4, {st_mode=S_IFREG|0644, st_size=118236, ...}) = 0
> mmap(NULL, 118236, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7f8537371000
> close(4) = 0
> access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or
> directory)
> open("/lib/libgcc_s.so.1", O_RDONLY) = 4
> read(4, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200-
> \0\0\0\0\0\0"..., 832) = 832
> fstat(4, {st_mode=S_IFREG|0644, st_size=92552, ...}) = 0
> mmap(NULL, 2188280, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4,
> 0) = 0x7f8536bf7000
> mprotect(0x7f8536c0d000, 2093056, PROT_NONE) = 0
> mmap(0x7f8536e0c000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|
> MAP_DENYWRITE, 4, 0x15000) = 0x7f8536e0c000
> close(4) = 0
> mprotect(0x7f8536e0c000, 4096, PROT_READ) = 0
> munmap(0x7f8537371000, 118236) = 0
> write(3, "======= Backtrace: =========\n", 29======= Backtrace:
> =========
> ) = 29
> writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"+0x", 3}, {"775b6", 5},
> {")", 1}, {"[0x", 3}, {"7f8536e855b6", 12}, {"]\n", 2}], 8/lib/libc.so.
> 6(+0x775b6)[0x7f8536e855b6]
> ) = 41
> writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"+0x", 3}, {"7dd96", 5},
> {")", 1}, {"[0x", 3}, {"7f8536e8bd96", 12}, {"]\n", 2}], 8/lib/libc.so.
> 6(+0x7dd96)[0x7f8536e8bd96]
> ) = 41
> writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"realloc", 7}, {"+0x",
> 3}, {"f0", 2}, {")", 1}, {"[0x", 3}, {"7f8536e8c0b0", 12}, {"]\n",
> 2}], 9/lib/libc.so.6(realloc+0xf0)[0x7f8536e8c0b0]
> ) = 45
> writev(3, [{"./unittest", 10}, {"[0x", 3}, {"400be3", 6}, {"]\n", 2}],
> 4./unittest[0x400be3]
> ) = 21
> writev(3, [{"./unittest", 10}, {"[0x", 3}, {"401217", 6}, {"]\n", 2}],
> 4./unittest[0x401217]
> ) = 21
> writev(3, [{"/lib/libc.so.6", 14}, {"(", 1}, {"__libc_start_main",
> 17}, {"+0x", 3}, {"fd", 2}, {")", 1}, {"[0x", 3}, {"7f8536e2cc4d",
> 12}, {"]\n", 2}], 9/lib/libc.so.6(__libc_start_main+0xfd)
> [0x7f8536e2cc4d]
> ) = 55
> writev(3, [{"./unittest", 10}, {"[0x", 3}, {"4006d9", 6}, {"]\n", 2}],
> 4./unittest[0x4006d9]
> ) = 21
> write(3, "======= Memory map: ========\n", 29======= Memory map:
> ========
> ) = 29
> open("/proc/self/maps", O_RDONLY) = 4
> read(4, "00400000-00402000 r-xp 00000000 "..., 1024) = 1024
> write(3, "00400000-00402000 r-xp 00000000 "..., 102400400000-00402000
> r-xp 00000000 08:07 785378 /home/iroman/
> Desktop/Project/DynamicArray/unittest
> 00601000-00602000 r--p 00001000 08:07
> 785378 /home/iroman/Desktop/Project/
> DynamicArray/unittest
> 00602000-00603000 rw-p 00002000 08:07
> 785378 /home/iroman/Desktop/Project/
> DynamicArray/unittest
> 01c77000-01c98000 rw-p 00000000 00:00
> 0 [heap]
> 7f8530000000-7f8530021000 rw-p 00000000 00:00 0
> 7f8530021000-7f8534000000 ---p 00000000 00:00 0
> 7f8536bf7000-7f8536c0d000 r-xp 00000000 08:06
> 2645 /lib/libgcc_s.so.1
> 7f8536c0d000-7f8536e0c000 ---p 00016000 08:06
> 2645 /lib/libgcc_s.so.1
> 7f8536e0c000-7f8536e0d000 r--p 00015000 08:06
> 2645 /lib/libgcc_s.so.1
> 7f8536e0d000-7f8536e0e000 rw-p 00016000 08:06
> 2645 /lib/libgcc_s.so.1
> 7f8536e0e000-7f8536f88000 r-xp 00000000 08:06
> 8050 /lib/libc-2.11.1.so
> 7f8536f88000-) = 1024
> read(4, "7f8537187000 ---p 0017a000 08:06"..., 1024) = 980
> write(3, "7f8537187000 ---p 0017a000 08:06"..., 9807f8537187000 ---p
> 0017a000 08:06 8050 /lib/libc-2.11.1.so
> 7f8537187000-7f853718b000 r--p 00179000 08:06
> 8050 /lib/libc-2.11.1.so
> 7f853718b000-7f853718c000 rw-p 0017d000 08:06
> 8050 /lib/libc-2.11.1.so
> 7f853718c000-7f8537191000 rw-p 00000000 00:00 0
> 7f8537191000-7f85371b1000 r-xp 00000000 08:06
> 7967 /lib/ld-2.11.1.so
> 7f853738e000-7f8537391000 rw-p 00000000 00:00 0
> 7f85373ad000-7f85373b0000 rw-p 00000000 00:00 0
> 7f85373b0000-7f85373b1000 r--p 0001f000 08:06
> 7967 /lib/ld-2.11.1.so
> 7f85373b1000-7f85373b2000 rw-p 00020000 08:06
> 7967 /lib/ld-2.11.1.so
> 7f85373b2000-7f85373b3000 rw-p 00000000 00:00 0
> 7fffc20b5000-7fffc20ca000 rw-p 00000000 00:00
> 0 [stack]
> 7fffc21ff000-7fffc2200000 r-xp 00000000 00:00
> 0 [vdso]
> ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00
> 0 [vsyscall]
> ) = 980
> read(4, "", 1024) = 0
> close(4) = 0
> rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
> gettid() = 4334
> tgkill(4334, 4334, SIGABRT) = 0
> --- SIGABRT (Aborted) @ 0 (0) ---
> +++ killed by SIGABRT +++
> Emergency Stop
> //////////////////////////// valgrind list ////////////////////////
> ==4380== Memcheck, a memory error detector
> ==4380== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et
> al.
> ==4380== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for
> copyright info
> ==4380== Command: ./unittest
> ==4380==
> /// Stage 1 ///
> alloc_array returned NULL
> arrayInt = 51b0040
> DeleteArray returned NULL
> DeleteArray executed 1
> /// Stage 2 ///
> arrayInt = 51b0130
> Add returned NULL
> Add returned NULL
> ==4380== Conditional jump or move depends on uninitialised value(s)
> ==4380== at 0x400AEF: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4011B2: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380==
> 97: Head added
> Add added 7
> 112: realloc size = 16
> 119: reallocated sucessfuly
> ==4380== Invalid write of size 8
> ==4380== at 0x400C7B: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b02f0 is 15 bytes after a block of size 17
> alloc'd
> ==4380== at 0x4C275A2: realloc (vg_replace_malloc.c:525)
> ==4380== by 0x400BE2: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380==
> ==4380== Invalid write of size 8
> ==4380== at 0x400C82: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b02f8 is not stack'd, malloc'd or (recently)
> free'd
> ==4380==
> ==4380== Invalid write of size 8
> ==4380== at 0x400C8A: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b0300 is not stack'd, malloc'd or (recently)
> free'd
> ==4380==
> ==4380== Invalid write of size 8
> ==4380== at 0x400C92: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4011E4: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b0308 is not stack'd, malloc'd or (recently)
> free'd
> ==4380==
> Add added 2
> 112: realloc size = 32
> 119: reallocated sucessfuly
> ==4380== Invalid write of size 8
> ==4380== at 0x400C7B: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b0420 is not stack'd, malloc'd or (recently)
> free'd
> ==4380==
> ==4380== Invalid write of size 8
> ==4380== at 0x400C82: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b0428 is not stack'd, malloc'd or (recently)
> free'd
> ==4380==
> ==4380== Invalid write of size 8
> ==4380== at 0x400C8A: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b0430 is not stack'd, malloc'd or (recently)
> free'd
> ==4380==
> ==4380== Invalid write of size 8
> ==4380== at 0x400C92: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== Address 0x51b0438 is not stack'd, malloc'd or (recently)
> free'd
> ==4380==
> ==4380== Conditional jump or move depends on uninitialised value(s)
> ==4380== at 0x400925: cmp (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4E650FA: msort_with_tmp (msort.c:65)
> ==4380== by 0x4E656EB: qsort_r (msort.c:294)
> ==4380== by 0x400CD4: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380==
> ==4380== Conditional jump or move depends on uninitialised value(s)
> ==4380== at 0x400932: cmp (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x4E650FA: msort_with_tmp (msort.c:65)
> ==4380== by 0x4E656EB: qsort_r (msort.c:294)
> ==4380== by 0x400CD4: Add (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380== by 0x401216: main (in /home/iroman/Desktop/Project/
> DynamicArray/unittest)
> ==4380==
> unittest: DynamicArray.c:79: cmp: Assertion `((struct iterator *)A)-
>>ops != ((void *)0) && ((struct iterator *)B)->ops != ((void *)0)'
> failed.
> ==4380==
> ==4380== HEAP SUMMARY:
> ==4380== in use at exit: 321 bytes in 7 blocks
> ==4380== total heap usage: 15 allocs, 8 frees, 930 bytes allocated
> ==4380==
> ==4380== LEAK SUMMARY:
> ==4380== definitely lost: 48 bytes in 3 blocks
> ==4380== indirectly lost: 0 bytes in 0 blocks
> ==4380== possibly lost: 0 bytes in 0 blocks
> ==4380== still reachable: 273 bytes in 4 blocks
> ==4380== suppressed: 0 bytes in 0 blocks
> ==4380== Rerun with --leak-check=full to see details of leaked memory
> ==4380==
> ==4380== For counts of detected and suppressed errors, rerun with: -v
> ==4380== Use --track-origins=yes to see where uninitialised values
> come from
> ==4380== ERROR SUMMARY: 11 errors from 11 contexts (suppressed: 4 from
> 4)
> Emergency Stop
>
> thanks
>

Eric Sosman

3/30/2011 1:42:00 AM

0

On 3/29/2011 4:22 PM, qqqqqq wwwwww wrote:
> Hi, my name is Ivanov Roman. Can you give me any advice: realloc has
> failed in the function Add?
> [...]

It's because you are trying to realloc() a memory region that
was not obtained from malloc() and friends. Specifically, you are
passing realloc() a pointer to the `auto' variable dataInt, defined
in main().

--
Eric Sosman
esosman@ieee-dot-org.invalid

Barry Schwarz

3/30/2011 3:20:00 AM

0

On Tue, 29 Mar 2011 13:22:06 -0700 (PDT), qqqqqq wwwwww
<iromcorp@gmail.com> wrote:

>Hi, my name is Ivanov Roman. Can you give me any advice: realloc has
>failed in the function Add?

You need to help us out here. Your code is abysmally unreadable.

>
>///////////////// DynamicArray.h /////////////////////////////
>#ifndef _DYNAMICARRAY_H
>#define _DYNAMICARRAY_H
>
>#include <stdlib.h>
>#include <assert.h>
>#include <string.h>
>
>struct iterator;
>
>struct iterator_ops {
> void * (* GetData) (struct iterator * this);
> int (* Delete) (struct iterator * this);
>};
>
>struct iterator * alloc_iter (void * data, size_t size);
>
>struct dyn_array;
>
>struct array_ops {
> int (* Add) (struct dyn_array * this, void * data, size_t size);
> int (* Del) (struct dyn_array * this, int position);
> int (* DeleteArray) (struct dyn_array * this);
> void * (* Get) (struct dyn_array * this, int n);
> struct iterator * (* Search) (const void * key,
> const struct dyn_array * this);
> struct iterator * (* GetBegin) (struct dyn_array * this);
> int (* cmp) (const void * A, const void * B);
> int (* cmp_content) (const void * A, const void * B);
> int (* SetCompare) (struct dyn_array * this,
> int (* cmp_user) (const void * A, const void * B));
>};
>
>struct dyn_array * alloc_array (int (* cmp_content) (const void * A,
> const void * B));

First off, make things easier for us to find. Declare your structure
types first, then your function prototypes. Making us hop back and
forth is one way to make us lose interest quickly.

>
>#endif // _DYNAMICARRAY_H
>
>////////////////////// DynamicArray.c ///////////////////////////
>#include <stdio.h>
>
>#include "DynamicArray.h"
>

snip

>
>struct iterator * alloc_iter (void * data, size_t size) {
> /*if (size < 1)
> return NULL;*/

Don't make us wade through code you don't compile.

>
> struct iterator * result = (struct iterator *)malloc(sizeof(struct
>iterator));

The cast serves no purpose. It would make the code much easier to
read if you used the simpler construct
struct iterator *result = malloc(sizeof *result);

> if (result == (struct iterator *)NULL)

Another useless cast.

> return NULL;
>
> result->owner = NULL;
> result->data = data;
> result->size = size;
> result->ops = (struct iterator_ops*)malloc(sizeof(struct
>iterator_ops));
>
> if (result->ops == NULL) {

Strange that you didn't use the cast here.

> free(result);
> return NULL;
> }
>
> result->ops->GetData = GetData;
> result->ops->Delete = Delete;
> return result;
>};
>
>struct dyn_array {
> struct iterator * begin;
> struct array_ops * ops;
> int count_total;
> int count_filled;
>};

Please put all you declarations near the top of the file.

snip

>int cmp (const void * A, const void * B) {
> assert(A != NULL && B != NULL);
> assert(((struct iterator *)A)->ops != NULL &&
> ((struct iterator *)B)->ops != NULL);
> assert(((struct iterator *)A)->data != NULL &&
> ((struct iterator *)B)->data != NULL);
> assert(((struct iterator *)A)->owner != NULL &&
> ((struct iterator *)B)->owner != NULL);
> assert(((struct iterator *)A)->owner == ((struct iterator *)B)-
>>owner);

This entire function has the most obnoxious case of overcasting I have
ever seen. On top of that, you cast away the constant qualifier which
you should never do.

At the top of the function, add some code of the form
const struct iterator *AA = (const struct iterator *)A;
const struct iterator *BB = (const struct iterator *)B;
and replace every cast operator and operand with AA and BB.

> if (((struct iterator *)A)->owner->begin == A && (((struct
>iterator *)A)->owner->ops->cmp_content(((struct iterator *)A)->data,
> ((struct iterator *)B)->data) > 0)) {

That will allow this really ugly statement to become
if (AA->owner->begin == A &&
AA->owner->ops->cmp_content(AA->data, BB->data) > 0) {

> printf("Begin moved\n");
> ((struct iterator *)A)->owner->begin = (struct iterator *)B;
> }
>
> if (((struct iterator *)B)->owner->begin == B && (((struct
>iterator *)A)->owner->ops->cmp_content(((struct iterator *)A)->data,
> ((struct iterator *)B)->data) < 0)) {
> printf("Begin moved\n");
> ((struct iterator *)B)->owner->begin = (struct iterator *)A;
> }
> return ((struct iterator *)A)->owner->ops->cmp_content(((struct
>iterator *)A)->data,
> ((struct iterator *)B)->data);
>}
>
>int Add (struct dyn_array * this, void * data, size_t size) {
> if (this == NULL)
> return -1;
>
> if (size < 1)
> return -1;
>
> if (this->count_total == 0) {
> printf("97: Head added\n");
> struct iterator * i = alloc_iter(data, size);

In C90, declarations must be at the top of a block prior to any
statements.

> if (i == NULL)
> return -1;
> i->owner = this;
> this->begin = i;
> this->count_total = 1;
> this->count_filled = 1;
> return 0;
>
> } else {
>
> if (this->begin == NULL) {
> printf("111\n");
> return -1;
> }
> if (this->count_filled == this->count_total) {
> struct iterator * buf = this->begin;
>
> printf("112: realloc size = %d\n", sizeof(struct iterator
>*) * this->count_total * 2);

%d requires an int. sizeof evaluates to a size_t which need not be
the same. You should cast the value to match the format.

>
> this->begin = realloc(this->begin,
> sizeof(struct iterator *) * this->count_total * 2 +
>1);

If realloc fails, this causes a memory leak. this-> begin will be set
to NULL making it impossible to free the memory it used to point to.

>
> printf("119: reallocated sucessfuly\n");
> if (this->begin == NULL) {
> this->begin = buf;
> return -1;
> }
> this->count_total *=2;
> }
> }
> struct iterator * i = alloc_iter(data, size);
> if (i == NULL) {
> return -1;
> }
> i->owner = this;
> *(this->begin + this->count_filled) = *i;
> free(i);
> qsort(this->begin, this->count_filled, this->begin->size, this-
>>ops->cmp);
>
> this->count_filled++;
>
> return 0;
>}
>
>int Del (struct dyn_array * this, int position) {
> if (this == NULL)
> return -1;
>
> if (position > this->count_filled)
> return -1;
>
> free(this->begin + position);
>
> memmove(this->begin + position, this->begin + position + 1,
> this->count_filled - position);

The count in memmove is bytes. You are missing a scale factor,
probably sizeof something.

> return 0;
>}
>
>int DeleteArray (struct dyn_array * this) {
> if (this == NULL)
> return -1;
>
> if (this->begin == NULL) {
> free(this->ops);
> free(this);
> return 0;
> }
>
> int position = 0;
> for (; position < this->count_filled; position ++)
> (this->begin + position)->ops->Delete(this->begin + position);
>
> free (this->ops);
> free (this);
> return 0;
>}
>
>void * Get (struct dyn_array * this, int n) {
> if (this == NULL)
> return NULL;
>
> if (n > this->count_filled)
> return NULL;
>
> if ((this->begin + n) == NULL)
> return NULL;
>
> return (this->begin + n)->ops->GetData(this->begin + n);
>}
>
>struct iterator * Search (const void * key, const struct dyn_array *
>this) {
> return bsearch(key, this->begin, this->count_filled, this->begin-
>>size, this->ops->cmp);
>}
>
>struct iterator * GetBegin (struct dyn_array * this) {
> if (this == NULL)
> return NULL;
> return this->begin;
>}
>
>struct dyn_array * alloc_array (int (* cmp_content) (const void * A,
> const void * B)) {
> if (cmp_content == NULL)
> return NULL;
>
> struct dyn_array * result = (struct dyn_array
>*)malloc(sizeof(struct dyn_array));
>
> result->begin = NULL;
> result->ops = (struct array_ops *)malloc(sizeof(struct
>array_ops));
>
> if (result->ops == NULL) {
> free(result);
> return NULL;
> }
> result->ops->Add = Add;
> result->ops->Del = Del;
> result->ops->DeleteArray = DeleteArray;
> result->ops->Get = Get;
> result->ops->GetBegin = GetBegin;
> result->ops->Search = Search;
> result->ops->SetCompare = SetCompare;
> result->ops->cmp = cmp;
> result->ops->cmp_content = cmp_content;
>
> return result;
>}
>/////////////////// DynArray_unittest.c //////////////////////
>#include "DynamicArray.h"
>#include <stdio.h>
>
>int cmpInt (const void * a, const void * b){
> return ( *(int *)a - *(int *)b );
>}
>
>int main() {
>
> ////// Stage 1 //////
> printf("/// Stage 1 ///\n");
> // alloc_arrayint ((* cmp_content) (const void * A, const void *
>B))

This demonstrates why you should not use // style comments in code you
send to Usenet.

> struct dyn_array * arrayInt;
>
> arrayInt = alloc_array(NULL);
> if (arrayInt == NULL)
> printf("alloc_array returned NULL\n");
>
> arrayInt = alloc_array(cmpInt);
> printf("arrayInt = %x\n", arrayInt);
>
> // int DeleteArray (struct dyn_array * this)
> if (DeleteArray(NULL) == -1)
> printf("DeleteArray returned NULL\n");
>
> if (DeleteArray(arrayInt) == 0)
> printf("DeleteArray executed 1\n");
>
> ////// Stage 2 //////
> printf("/// Stage 2 ///\n");
>
> arrayInt = alloc_array(cmpInt);
> printf("arrayInt = %x\n", arrayInt);
>
> // int Add (struct dyn_array * this, void * data, size_t size)
> int dataInt = 0;
> if (Add(NULL, &dataInt, sizeof(int)) == -1)
> printf("Add returned NULL\n");
>
> if (Add(arrayInt, &dataInt, 0) == -1)
> printf("Add returned NULL\n");
>
> dataInt = 7;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 7\n");
> dataInt = 2;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 2\n");
> dataInt = 45;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 45\n");
> dataInt = 78;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 78\n");
> dataInt = 25;
> if (Add(arrayInt, &dataInt, sizeof(int)) == 0)
> printf("Add added 25\n");
>
> if (DeleteArray(arrayInt) == 0)
> printf("DeleteArray executed successfully 1\n");
>
> return (EXIT_SUCCESS);
>}

--
Remove del for email

Ike Naar

3/30/2011 7:09:00 AM

0

On 2011-03-30, Barry Schwarz <schwarzb@dqel.com> wrote:
> On Tue, 29 Mar 2011 13:22:06 -0700 (PDT), qqqqqq wwwwww
><iromcorp@gmail.com> wrote:
>>int cmp (const void * A, const void * B) {
>> assert(A != NULL && B != NULL);
>> assert(((struct iterator *)A)->ops != NULL &&
>> ((struct iterator *)B)->ops != NULL);
>> assert(((struct iterator *)A)->data != NULL &&
>> ((struct iterator *)B)->data != NULL);
>> assert(((struct iterator *)A)->owner != NULL &&
>> ((struct iterator *)B)->owner != NULL);
>> assert(((struct iterator *)A)->owner == ((struct iterator *)B)-
>>>owner);
>
> This entire function has the most obnoxious case of overcasting I have
> ever seen. On top of that, you cast away the constant qualifier which
> you should never do.
>
> At the top of the function, add some code of the form
> const struct iterator *AA = (const struct iterator *)A;
> const struct iterator *BB = (const struct iterator *)B;
> and replace every cast operator and operand with AA and BB.

Those casts are also unnecessary.

const struct iterator *AA = A;
const struct iterator *BB = B;

Ike Naar

3/30/2011 7:53:00 AM

0

On 2011-03-29, qqqqqq wwwwww <iromcorp@gmail.com> wrote:
> Hi, my name is Ivanov Roman. Can you give me any advice: realloc has
> failed in the function Add?
>
> ///////////////// DynamicArray.h /////////////////////////////
> #ifndef _DYNAMICARRAY_H
> #define _DYNAMICARRAY_H

Don't use names that start with an underscore, they are reserved
for the implementation.

[snip]

> struct dyn_array {
> struct iterator * begin;
> struct array_ops * ops;
> int count_total;
> int count_filled;
> };

[snip]

> struct dyn_array * alloc_array (int (* cmp_content) (const void * A,
> const void * B)) {

This function is (I think) supposed to allocate and properly
initialize a struct dyn_array, but is doesn't initialize the
count_total and count_filled members. It almost looks like you
expect count_total to be automatically initialized to 0, but
that does not happen, you must explicitly set it to 0.

Ike Naar

3/30/2011 8:22:00 AM

0

On 2011-03-29, Gordon Burditt <gordonb.xwohw@burditt.org> wrote:
> It appears that your code is scribbling on memory it doesn't own.
> Fix that. It can cause malloc() and realloc() to malfunction.

What makes you reach that conclusion? OP's problem looks more like
an initialization failure (see elsethread), but of course I may
have missed something.

If you found a place where OP scribbled over non-owned memory,
then it would have been helpful to indicate where that happens.
It's easier to "fix that" if one knows what to fix.

Oh, by the way, why are you always deleting attribution lines?
Just curious. In any case, it makes the discussion harder to follow.

Oh, by the way, please don't top post.

gordonb.njjma

3/31/2011 1:39:00 AM

0

>> It appears that your code is scribbling on memory it doesn't own.
>> Fix that. It can cause malloc() and realloc() to malfunction.
>
> What makes you reach that conclusion? OP's problem looks more like
> an initialization failure (see elsethread), but of course I may
> have missed something.

The complaints from Valgrind.

I'm still trying to figure out how he came to the conclusion that
realloc() failed. Although Add() may have failed, there are several
ways it can fail before calling realloc().

> If you found a place where OP scribbled over non-owned memory,
> then it would have been helpful to indicate where that happens.
> It's easier to "fix that" if one knows what to fix.

They are already identified in the complaints from Valgrind.
Since the OP posted them, I hope he read them.

> Oh, by the way, why are you always deleting attribution lines?
> Just curious. In any case, it makes the discussion harder to follow.

There's no proof that any of the attribution lines or From: lines
are accurate, and no reason to blame some individual for a post which
he may or may not have anything to do with.

> Oh, by the way, please don't top post.

I didn't. My comments were placed AFTER a quote from the OP, which
I commented on.

Keith Thompson

3/31/2011 3:26:00 AM

0

gordonb.njjma@burditt.org (Gordon Burditt) writes:
> Ike Naar <ike@sverige.freeshell.org> writes:
>> gordonb.njjma@burditt.org (Gordon Burditt) writes:
[...]
>> Oh, by the way, why are you always deleting attribution lines?
>> Just curious. In any case, it makes the discussion harder to follow.
>
> There's no proof that any of the attribution lines or From: lines
> are accurate,

True, but everybody knows that.

> and no reason to blame some individual for a post which
> he may or may not have anything to do with.

Nonsense, as always. There are plenty of good reasons to make a
reasonable attempt at proper attribution (all you have to do is *not*
delete the attribution lines), and no good reasons to refrain from
doing so.

>> Oh, by the way, please don't top post.
>
> I didn't. My comments were placed AFTER a quote from the OP, which
> I commented on.

Yes. You then needlessly quoted several hundred lines of the original
post.

Just this once, I grant permission to quote this article without a
proper attribution line, provided that this paragraph is quoted in full.
I, Keith Thompson, kst-u@mib.org, wrote this article.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ike Naar

3/31/2011 6:26:00 AM

0

On 2011-03-31, Gordon Burditt <gordonb.njjma@burditt.org> wrote:
> There's no proof that any of the attribution lines or From: lines
> are accurate, and no reason to blame some individual for a post which
> he may or may not have anything to do with.

Is there any proof that the 600+ lines of text you quoted are accurate?
Why snip the attribution lines, but not the text?

gazelle

3/31/2011 7:53:00 AM

0

In article <lnk4fg55tb.fsf@nuthaus.mib.org>,
Keith Thompson <kst-u@mib.org> wrote:
>gordonb.njjma@burditt.org (Gordon Burditt) writes:
>> Ike Naar <ike@sverige.freeshell.org> writes:
>>> gordonb.njjma@burditt.org (Gordon Burditt) writes:
>[...]
>>> Oh, by the way, why are you always deleting attribution lines?
>>> Just curious. In any case, it makes the discussion harder to follow.
>>
>> There's no proof that any of the attribution lines or From: lines
>> are accurate,
>
>True, but everybody knows that.
>
>> and no reason to blame some individual for a post which
>> he may or may not have anything to do with.
>
>Nonsense, as always. There are plenty of good reasons to make a
>reasonable attempt at proper attribution (all you have to do is *not*
>delete the attribution lines), and no good reasons to refrain from
>doing so.

Chick fight!

--
"The anti-regulation business ethos is based on the charmingly naive notion
that people will not do unspeakable things for money." - Dana Carpender

Quoted by Paul Ciszek (pciszek at panix dot com). But what I want to know
is why is this diet/low-carb food author doing making pithy political/economic
statements?

Nevertheless, the above quote is dead-on, because, the thing is - business
in one breath tells us they don't need to be regulated (which is to say:
that they can morally self-regulate), then in the next breath tells us that
corporations are amoral entities which have no obligations to anyone except
their officers and shareholders, then in the next breath they tell us they
don't need to be regulated (that they can morally self-regulate) ...