The following code when tested, gives output as
1
0
0
2
0
which is amazing because ptr[3], ptr[4] did not have any memory allocation. Although they stored value in them and prints it. I tried the same code for few larger i's in ptr[i] which again compiled successfully and gives result but for very large value of i, of the order of 100000,program get crashed. if calloc() allocates such a large memory on single call then it is not worth effective. So how calloc() works? Where is this discrepancy?
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));//allocates memory to 3 integer
int i = 0;
*ptr = 1;
*(ptr+3) = 2;//although memory is not allocated but get initialized
for( i =0 ; i<5 ; ++i){
printf("%d\n",*ptr++);
}
}
After that i tried this code which continuously runs without any output
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));
int i = 0;
*ptr = 1;
*(ptr+3) = 2;
//free(ptr+2);
for( ; ptr!=NULL ;)
{
//printf("%d\n",*ptr++);
i++;
}
printf("%d",i);
}
You are confounding two kinds of memory allocation: the kernel's and libc's.
When you ask malloc or calloc for 5 bytes, it does not turn around and ask the kernel for 5 bytes. That would take forever. Instead, the libc heap system obtains larger blocks of memory from the kernel, and subdivides it.
Therefore, when you ask for a small amount of memory, there is usually plenty of more accessible memory right after it that has not been allocated yet by libc, and you can access it. Of course, accessing it is an instant recipe for bugs.
The only time that referencing off the end will get a SIGnal is if you happen to be at the very end of the region acquired from the kernel.
I recommend that you try running your test case under valgrind for additional insight.
The code that you have has undefined behavior. However, you do not get a crash because malloc and calloc indeed often allocate more memory than you ask.
One way to tell how much memory you've got is to call realloc with increasing size, until the pointer that you get back is different from the original. Although the standard does not guarantee that this trick is going to work, very often it would produce a good result.
Here is how you can run this experiment:
int *ptr = calloc(1,sizeof(int));
// Prevent expansion of the original block
int *block = calloc(1, sizeof(int));
int *tmp;
int k = 1;
do {
tmp = realloc(ptr, k*sizeof(int));
k++;
} while (tmp == ptr);
printf("%d\n", k-1);
This prints 4 on my system and on ideone (demo on ideone). This means that when I requested 4 bytes (i.e. one sizeof(int) from calloc, I got enough space for 16 bytes (i.e. 4*sizeof(int)). This does not mean that I can freely write up to fourints after requesting memory for a singleint`, though: writing past the boundary of the requested memory is still undefined behavior.
calloc is allocating memory for 3 int's in the given snippet. Actually you are accessing unallocated memory. Accessing unallocated memory invokes undefined behavior.
calloc allocates only the amount of memory that you asked, which in your case in for 3 int variables
but it doesnt create a bound on the pointer that it has created (in your case ptr). so you can access the unallocated memory just by incrementing the pointer. thats exactly whats happening in your case..
Related
In the example below I have allocated 20 bytes of memory to extend an array by 5 integers. After that I have set the last element to 15 and then reallocated the pointer to 4 bytes (1 integer). Then I print the first 10 elements of the array (it only consists of 6 at this point) and the 9th (which I've previously set to 15) is printed without warnings or errors.
The code :
#include <stdlib.h>
#include <stdio.h>
int main()
{
int arr[5] = {0};
int *ptr = &arr[0];
ptr = malloc(5 * sizeof(int));
arr[9] = 15;
ptr = realloc(ptr, 1 * sizeof(int));
for (int i = 0; i < 10; ++i)
{
printf("%d\n", arr[i]);
}
free(ptr);
return 0;
}
The result after compiling and running :
0
0
0
0
0
32766
681279744
-1123562100
-1261131712
15
My question is as follows : Why is the 9th element of the array still 15? (why am I able to access it?; Shouldn't the allocated memory be at the first free block of memory my compiler finds and not connected to the array's buffer whatsoever?)
The behaviour of malloc() \ realloc() is irrelevant in this case because in the code in the question the content of arr rather than ptr is modified and displayed, and arr is not dynamically allocated or reallocated. So there is no out-of-bounds access in the dynamic memory. The out-of-bounds access to arr[] has undefined behaviour. You will be stomping on memory not allocated to arr. In some cases that will modify adjacent variables, but in this case you have none, so since stacks most often grow downward, you may be modifying the local variables of the calling function or corrupting the return address of the current function - this being main() even that might not cause any noticeable error. In other cases it will lead to a crash.
However, had you modified ptr[15] and reallocated, then displayed the content at ptr it is most likely that you see a similar result because avoid an unnecessary data move, realloc() reuses the same memory block when the allocation is reduced, and simply reduces its size, returning the remainder to the heap.
Returning memory to the heap, does not change its content or make it inaccessible, and C does not perform any bounds checking, so if you code to access memory that is not part of the allocation it will let you. It simply makes the returned block available for allocation.
Strictly it is undefined behaviour, so other behaviour is possible, but generally C does not generate code to do anything other than the bare minimum required - except possibly in some cases to support debugging.
Your description of what the program is doing is all wrong.
In the example below I have allocated 20 bytes of memory to extend an array by 5 integers
No, you don't. You can't extend arr. It's just impossible.
After that I have set the last element to 15
No - because you didn't extend the array so index 9 does not represent the last element. You simply write outside the array.
Look at these lines:
int *ptr = &arr[0];
ptr = malloc(5 * sizeof(int));
First you make ptr point to the first element in arr but rigth after you you make ptr point to some dynamic allocated memory which have absolutely no relation to arr. In other words - the first line can simply be deleted (and probably the compiler will).
In the rest of your program you never use ptr for anything. In other words - you can simply remove all code using ptr. It has no effect.
So the program could simply be:
int main()
{
int arr[5] = {0};
arr[9] = 15;
for (int i = 0; i < 10; ++i)
{
printf("%d\n", arr[i]);
}
return 0;
}
And it has undefined behavior because you access arr out of bounds.
Why is the 9th element of the array still 15?
The "most likely reality" is that the OS provides a way to allocate area/s of virtual pages (which aren't necessarily real memory and should be considered "pretend/fake memory"), and malloc() carves up the allocated "pretend/fake memory" (and allocates more area/s of virtual pages if/when necessary, and deallocates areas of virtual pages if/when convenient).
Freeing "pretend/fake memory that was carved up by malloc()" probably does no more than alter some meta-data used to manage the heap; and is unlikely to cause "pretend/fake memory" to be deallocated (and is even less likely to effect actual real physical RAM).
Of course all of this depends on the environment the software is compiled for, and it can be completely different; so as far as C is concerned (at the "C abstract machine" level) it's all undefined behavior (that might work like I've described, but may not); and even if it does work like I've described there's no guarantee that something you can't know about (e.g. a different thread buried in a shared library) won't allocate the same "pretend/fake memory that was carved up by malloc()" immediately after you free it and won't overwrite the data you left behind.
why am I able to access it?
This is partly because C isn't a managed (or "safe") language - for performance reasons; typically there are no checks for "array index out of bounds" and no checks for "used after it was freed". Instead, bugs cause undefined behavior (and may be critical security vulnerabilities).
int arr[5] = {0}; // these 5 integers are kept on the stack of the function
int *ptr = &arr[0]; // the pointer ptr is also on the stack and points to the address of arr[0]
ptr = malloc(5 * sizeof(int)); // malloc creates heap of size 5 * sizeof int and returns a ptr which points to it
// the ptr now points to the heap and not to the arr[] any more.
arr[9] = 15; //the array is of length 5 and arr[9] is out of the border of maximum arr[4] !
ptr = realloc(ptr, 1 * sizeof(int)); //does nothing here, since the allocated size is already larger than 1 - but it depends on implementation if the rest of 4 x integer will be free'd.
for (int i = 0; i < 10; ++i) // undefined behavior!
{
printf("%d\n", arr[i]);
}
free(ptr);
return 0;`
In short:
Whatever you do with/to a copy of the address of an array inside a pointer variable, it has no influence on the array.
The address copy creates no relation whatsoever between the array and memory allocated (and referenced by the pointer) by a later malloc.
The allocation will not be right after the array.
A realloc of a pointer with a copy of an array access does not work. Realloc only works with pointers which carry the result of a succesful malloc. (Which is probably why you inserted the malloc.)
Longer:
Here are some important facts on your code, see my comments:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int arr[5] = {0}; /* size 5 ints, nothing will change that */
int *ptr = &arr[0]; /* this value will be ignored in the next line */
ptr = malloc(5 * sizeof(int)); /* overwrite value from previous line */
arr[9] = 15; /* arr still only has size 5 and this access beyond */
ptr = realloc(ptr, 1 * sizeof(int)); /* irrelevant, no influence on arr */
for (int i = 0; i < 10; ++i) /* 10 is larger than 5 ... */
{
printf("%d\n", arr[i]); /* starting with 5, this access beyond several times */
}
free(ptr);
return 0;
}
Now let us discuss your description:
In the example below I have allocated 20 bytes of memory ....
True, in the line ptr = malloc(5 * sizeof(int)); (assuming that an int has 4 bytes; not guaranteed, but let's assume it).
... to extend an array by 5 integers.
No. No attribute of the array is affected by this line. Especially not the size.
Note that with the malloc, the line int *ptr = &arr[0]; is almost completely ignored. Only the part int *ptr; remains relevant. The malloc determines the value in the pointer and there is no relation to the array whatsoever.
After that I have set the last element to 15 ...
No, you access memory beyond the array. The last useable array element is arr[4] noce code until now has changed that. Judgin from the output, which still contains "15", you got "lucky", the value has not killed anything and still is in memory. But it is practically unrelated to the array and is also practically guaranteed outside of the allocated memory referenced by ptr.
... and then reallocated the pointer to 4 bytes (1 integer).
True. But I do not really get the point you try to make.
Then I print the first 10 elements of the array ...
No, you print the first 5 elements of the array, i.e. all of them.
Then you print 3 values which happen to be inside memory which you should not access at all. Afterwards you print a fifth value outside of the array, which you also should not access, but which happens to be still be the 15 you wrote there earlier - and should not have in the first place either.
... (it only consists of 6 at this point) ...
You probabyl mean 5 values from the array and 1 from ptr, but they are unrelated and unlikely to be consecutive.
... and the 9th (which I've previously set to 15) is printed without warnings or errors.
There is no 9th, see above. Concerning the lack of errors, well, you are not always lucky enough to be told by the compiler or the runtime that you make a mistake. Life would be so much easier if they could notify you of reliably all mistakes.
Let us go on with your comments:
But isn't arr[9] part of the defined heap?
No. I am not sure what you mean by "the defined heap", but it is surely neither part of the array nor the allocated memory referenced by the pointer. The chance that the allocation is right after the array is as close to zero as it gets - maybe not precisely 0, but you simply are not allowed to assume that.
I have allocated 20 bytes, ...
On many current machines, but assuming that an int has four bytes is also not a afe assumption. However, yes, lets assume that 5 ints have 20 bytes.
... so arr should now consist of 10 integers, instead of 5.
Again no, whatever you do via ptr, it has no influence on the array and there is practically no chance that the ptr-referenced memory is right after the array by chance. It seems that you assume that copying the address of the array into the pointer has an influence on array. That is not the case. It had once a copy of the arrays address, but even that has been overwritten one line later. And even if it had not been overwritten, reallocing the ptr would make an error (that is why you inserted the malloc line, isn't it?) but still not have any effect on the array or its size.
... But I don't think I am passing the barrier of the defined heap.
Again, lets assume that by "the defined heap" you mean either the array or the allocated memory referenced by ptr. Neither can be assumed to contain the arr[9] you access. So yes, you ARE accessing outside of any memory you are allowed to access.
I shouldn't be able to access arr[9], right?
Yes and no. Yes, you are not allowed to do that (with or without the realloc to 1).
No, you cannot expect to get any helpful error message.
Let's look at your comment to another answer:
My teacher in school told me that using realloc() with a smaller size than the already allocated memory frees it until it becomes n bytes.
Not wrong. It is freed, which means you are not allowed to use it anymore.
It is also theoretically freed so that it could be used by the next malloc. That does however not mean that the next malloc will. In no case implies freeing memory any change to the content of that freed memory. It definitly could change, but you cannot expect it or even rely on it. Tom Kuschels answer to this comment is also right.
I can't understand the reason of the output pf the following program
#include <stdio.h>
#include <stdlib.h>
int main(){
int* ip = (int*)malloc(100*sizeof(int));
if (ip){
int i;
for (i=0; i < 100; i++)
ip[i] = i*i;
}
free(ip);
int* ip2 = (int*)malloc(10*sizeof(int));
printf("%d\n", ip[5]);
printf("%d\n", ip2[5]);
ip[5] = 10;
printf("%d\n", ip2[5]);
return 0;
}
the output shows that ip & ip2 will have the same reference in the heap.
when we allocate a 100 int in(ip2) how did it return the same reference for ip1.
is it a feature of malloc function?
I know that malloc work like "new",right?
if it does then it should return some random reference,right?
All your outputs are undefined behavior, so they're not indicative of anything:
printf("%d\n", ip[5]); // ip was freed, so the memory it points to may not be accessed
printf("%d\n", ip2[5]); // reading uninitialized memory
ip[5] = 10; // writing to freed memory
printf("%d\n", ip2[5]); // still reading uninitialized memory
Generally, it's entirely possible that ip2 gets the same address that ip had. But you're not testing that in your code. You could do that like this, for instance:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* ip = (int*)malloc(100 * sizeof(int));
printf("%p\n", ip);
free(ip);
int* ip2 = (int*)malloc(100 * sizeof(int));
printf("%p\n", ip2);
free(ip2);
}
When I run that, I do actually get the same address twice (but there's no guarantee that this happens).
I don't really see what your problem is.
It is completely up to the library where it allocates the memory which is returned to you. Especially, it may or may not use the most recently freed memory block, as long as it is still free.
Your first malloc() reserves some memory, you write to it and then you free it.
Your second malloc() reserves some memory, you read from it then you free it.
What you read in the second step is completely arbitrary and only by coincidence the same as wou wrote to it in the first step.
You code also shows undefined behaviour, because you are not allowed to access ip[5] after the free(it).
This is a undefined behaviour which you shouldn't rely on. When you allocate a memory typically from a page memory, when you free it isn't freed to OS immediately and when try allocating again most likely you get the same which is hot in the cache. Typical OS memory unit allocates the same size in next iteration from same memory freed blocks in LIFO fashion.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a = (int *)malloc(sizeof(int));
// int a[1];
int i;
for(i = 0; i < 876; ++i)
a[i] = i;
printf("%d",a[799]);
}
Why is this code working, even if, I am allocating only 1 int's space using malloc()?
Why is this code working? Even if, I am allocating only 1 int's space using malloc ? In such case answer in undefined behavior.
Allocating block of 4 bytes like
int *a = (int *)malloc(sizeof(int)); /* No need to cast the malloc result */
and accessing beyond that like
a[i] = i; /* upto i<1 behavior is guaranteed as only 4byte allocated, not after */
results in undefined behavior i.e anything can happen and you shouldn't depend on it doing the same thing twice.
Side note, type casting the result of malloc() is not required as malloc() return type void* & its automatically promoted safely into required type. Read Do I cast the result of malloc?
And always check the return value malloc(). for e.g
int *a = malloc(sizeof(int));
if( a != NULL) {
/* allocated successfully & do_something()_with_malloced_memory() */
}
else {
/* error handling.. malloc failed */
}
It seems to be working. There is absolutely zero guarantee it will work the same way after a recompile, or in a different environment.
Basically, here you're trying to access memory address, which is not allocated to your program (using any index other than 0). So, from your program point of view, the memory address is invalid. Accessing invalid memory location invokes undefined behaviour.
As others have explained, the behavior while accessing a memory region beyond what is allocated, is undefined. Run the same program on a system which is running memory intensive applications. You might see a SIGSEGV. Run your code through coverity static analysis and you will see it catching the buffer overrun.
Suppose I have the following piece of code in my program:
char *ptr;
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
ptr=malloc(sizeof(char)*10);
Will a pointer to the same memory block be assigned to ptr each time,or a separate piece of memory be reserved each time and its pointer assigned to ptr,resulting in memory leak each time malloc() is called?
I am still learning C so bear with me if it's too basic.I tried googling but found no answer.
EDIT::
Thanks for your answers.Please tell me if this approach of me deals with the memory leak risk.My program simply asks for names of 5 people and displays it,without using static arrays.After reading your answers,I put the free(ptr) inside the loop,else before I had planned to use it only once outside the loop,after the loop.Am I correct now?
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
int main ()
{
char *names[5],*ptr;
int i;
for(i=0;i<=4;i++)
{
ptr=malloc(sizeof(char)*10);
printf("Enter name no.%d : \n",i+1);
scanf("%s",ptr);
names[i]=malloc(strlen(ptr)+1);
strcpy(names[i],ptr);
free(ptr);
}
for(i=0;i<=4;i++)
printf("%s\n",names[i]);
}
malloc() will never return the same memory block multiple times, unless (of course) it has been free()'d since the last time it was returned. This is guaranteed by the C standard. Therefore, your code also leaks memory. Any memory allocator that handed out the same piece of memory twice would be worse than useless: Applications would step on their own toes, using the same piece of memory for different purposes, likely concurrently.
Edit: Barring buffer overflow issues, your code is correct in that it frees the 10-char buffers referenced via ptr. Calling free(ptr) just once, outside the loop, would indeed be incorrect. However, your code (as shown here) does not free the memory allocated later in the loop body stored in names[i].
A separate block of memory will be allocated each time, since C does not perform any garbage collection and no free calls are done in between the malloc calls. The first three blocks are leaked since you're not keeping pointers to them.
You can find out for yourself that the pointers are all distinct using a simple printf call:
for (int i = 0; i < 4; i++) {
ptr = malloc(10); // no need for sizeof(char), it's 1 by definition
printf("%p\n", ptr);
}
This should print four distinct numbers.
This will cause a memory leak assuming each call is successful, all but the memory allocated to the last malloc will be inaccessible. You either need to keep a pointer to each block allocated by malloc or you need to free between successive calls. so yes, malloc will attempt to allocate distinct block of memory for each call. A quick test could be as follows:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr;
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
ptr=malloc(sizeof(char)*10);
printf("%p\n", ptr);
}
This will print out the address allocated each time. If you added a free between each call to malloc you may end up with the same pointer, a quick test demonstrated this behavior.
Yes, each malloc call will allocate a new block, which means that the previous one will be leaked.
EDIT: answer to the edited part of the question
You are now correctly releasing the blocks to which ptr points, however you are not releasing those allocated for names. You would also need:
for(i=0;i<=4;i++) {
printf("%s\n",names[i]);
free(names[i]);
}
In your case, you could skip using ptr and work on names directly. Here's an equally [un]safe version:
char *names[5];
int i;
for(i=0; i < 5; i++)
{
names[i] = malloc(10);
printf("Enter name no.%d : \n",i+1);
scanf("%s",names[i]); // what if name is longer than 10 characters?
}
for(i=0; i < 5; i++)
{
printf("%s\n",names[i]);
free(names[i]);
}
However, operating system will reclaim the memory consumed by a process once the process exits, so in this simple example you don't have to worry, but I guess that this is only an illustration. I also assume that you don't care about user entering names longer than 10 characters which would write over the boundaries of allocated buffers.
Your second part is right: it's a memory leak.
A new block of memory is allocated each time you call malloc. This will create a memory leak as you have no way to reference the first three allocations to free them.
You can check memory leaks by using valgrind,its very useful in detecting memory leaks.
valgrind ./progr
I know that it's a common convention to pass the length of dynamically allocated arrays to functions that manipulate them:
void initializeAndFree(int* anArray, size_t length);
int main(){
size_t arrayLength = 0;
scanf("%d", &arrayLength);
int* myArray = (int*)malloc(sizeof(int)*arrayLength);
initializeAndFree(myArray, arrayLength);
}
void initializeAndFree(int* anArray, size_t length){
int i = 0;
for (i = 0; i < length; i++) {
anArray[i] = 0;
}
free(anArray);
}
but if there's no way for me to get the length of the allocated memory from a pointer, how does free() "automagically" know what to deallocate when all I'm giving it is the very same pointer? Why can't I get in on the magic, as a C programmer?
Where does free() get its free (har-har) knowledge from?
Besides Klatchko's correct point that the standard does not provide for it, real malloc/free implementations often allocate more space then you ask for. E.g. if you ask for 12 bytes it may provide 16 (see A Memory Allocator, which notes that 16 is a common size). So it doesn't need to know you asked for 12 bytes, just that it gave you a 16-byte chunk.
You can't get it because the C committee did not require that in the standard.
If you are willing to write some non-portable code, you may have luck with:
*((size_t *)ptr - 1)
or maybe:
*((size_t *)ptr - 2)
But whether that works will depend on exactly where the implementation of malloc you are using stores that data.
After reading Klatchko's answer, I myself tried it and ptr[-1] indeed stores the actual memory (usually more than the memory we asked for probably to save against segmentation fault).
{
char *a = malloc(1);
printf("%u\n", ((size_t *)a)[-1]); //prints 17
free(a);
exit(0);
}
Trying with different sizes, GCC allocates the memory as follows:
Initially memory allocated is 17 bytes.
The allocated memory is atleast 5 bytes more than requested size, if more is requested, it allocates 8 bytes more.
If size is [0,12], memory allocated is 17.
If size is [13], memory allocated is 25.
If size is [20], memory allocated is 25.
If size is [21], memory allocated is 33.
While it is possible to get the meta-data that the memory allocator places preceding the allocated block, this would only work if the pointer is truly a pointer to a dynamically allocated block. This would seriously affect the utility of function requiring that all passed arguments were pointers to such blocks rather than say a simple auto or static array.
The point is there is no portable way from inspection of the pointer to know what type of memory it points to. So while it is an interesting idea, it is not a particularly safe proposition.
A method that is safe and portable would be to reserve the first word of the allocation to hold the length. GCC (and perhaps some other compilers) supports a non-portable method of implementing this using a structure with a zero length array which simplifies the code somewhat compared to a portable solution:
typedef struct
{
size_t length ;
char alloc[0] ; // Compiler specific extension!!!
} tSizedAlloc ;
// Allocating a sized block
tSizedAlloc* blk = malloc( sizeof(tSizedAlloc) + length ) ;
blk->length = length ;
// Accessing the size and data information of the block
size_t blk_length = blk->length ;
char* data = blk->alloc ;
I know this thread is a little old, but still I have something to say. There is a function (or a macro, I haven't checked the library yet) malloc_usable_size() - obtains size of block of memory allocated from heap. The man page states that it's only for debugging, since it outputs not the number you've asked but the number it has allocated, which is a little bigger. Notice it's a GNU extention.
On the other hand, it may not even be needed, because I believe that to free memory chunk you don't have to know its size. Just remove the handle/descriptor/structure that is in charge for the chunk.
A non-standard way is to use _msize(). Using this function will make your code unportable. Also the documentation is not very clear on wheteher it will return the number passed into malloc() or the real block size (might be greater).
It's up to the malloc implementor how to store this data. Most often, the length is stored directly in front of the allocated memory (that is, if you want to allocate 7 bytes, 7+x bytes are allocated in reality where the x additional bytes are used to store the metadata). Sometimes, the metadata is both stored before and after the allocated memory to check for heap corruptions. But the implementor can as well choose to use an extra data structure to store the metadata.
You can allocate more memory to store size:
void my_malloc(size_t n,size_t size )
{
void *p = malloc( (n * size) + sizeof(size_t) );
if( p == NULL ) return NULL;
*( (size_t*)p) = n;
return (char*)p + sizeof(size_t);
}
void my_free(void *p)
{
free( (char*)p - sizeof(size_t) );
}
void my_realloc(void *oldp,size_t new_size)
{
// ...
}
int main(void)
{
char *p = my_malloc( 20, 1 );
printf("%lu\n",(long int) ((size_t*)p)[-1] );
return 0;
}
To answer the question about delete[], early versions of C++ actually required that you call delete[n] and tell the runtime the size, so it didn't have to store it. Sadly, this behaviour was removed as "too confusing".
(See D&E for details.)