Re: Problems reversing strings

From: Russell Hanneken (me_at_privacy.net)
Date: 09/07/04


Date: Mon, 06 Sep 2004 23:03:33 GMT

Mike Tyndall wrote:
> "Michael Brooks" <brooksm@taranis.physics.ox.ac.uk> wrote in message
> news:slrncjpm60.631.brooksm@nodens.physics.ox.ac.uk...
>> Mike allocated space for 200 chars with
>> new and assigned the resulting pointer to output, so he is able to store
>> the reversed string perfectly well. Unfortunately, he does all of this
>> to a local copy of output, which is returned to it's value before the
>> function call i.e. null.
>
> Are you sure it's a local copy? The following code prints 88:
>
> #include <iostream>
>
> void func(int* array);
>
> int main() {
> int array[10];
> array[0] = 5;
> func(array);
> std::cout << array[0] << "\n";
> return 0;
> }
>
> void func(int* array) {
> array[0] = 88;
> }

Yes, but that just proves you can modify one buffer through two different
variables. Let's walk through it step by step (the illustrations require a
monospace font):

1. int array[10];

First you create an array of 10 ints.

    array (main)
    +---+---+---+---+---+---+---+---+---+---+
    | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
    +---+---+---+---+---+---+---+---+---+---+

2. array[0] = 5;

Now you assign 5 to array[0].

    array (main)
    +---+---+---+---+---+---+---+---+---+---+
    | 5 | ? | ? | ? | ? | ? | ? | ? | ? | ? |
    +---+---+---+---+---+---+---+---+---+---+

3. func(array);

Now you call func and pass array. When you pass an array to a function,
you're actually passing the address of the array's first element. A new,
local variable, also called array, is created. It is assigned the address
of the first element of the array created in main. Let's pretend the
address is 0x30.

    array (main)
    +---+---+---+---+---+---+---+---+---+---+
    | 5 | ? | ? | ? | ? | ? | ? | ? | ? | ? |
    +---+---+---+---+---+---+---+---+---+---+
      ^
      |
      |
      |
    +------+
    | 0x30 |
    +------+
    array (func)

4. array[0] = 88;

Now you dereference the pointer called "array" (the variable local to func)
and access the array you created in main. You change the value of the first
element to 88.

    array (main)
    +----+---+---+---+---+---+---+---+---+---+
    | 88 | ? | ? | ? | ? | ? | ? | ? | ? | ? |
    +----+---+---+---+---+---+---+---+---+---+
      ^
      |
      |
      |
    +------+
    | 0x30 |
    +------+
    array (func)

5. Now, func ends. Its local variable goes away.

    array (main)
    +----+---+---+---+---+---+---+---+---+---+
    | 88 | ? | ? | ? | ? | ? | ? | ? | ? | ? |
    +----+---+---+---+---+---+---+---+---+---+

We're back in main. The rest is pretty clear.

Your original program did something different. Here's an example that
illustrates the problem with what you did:

    #include <cstring>

    void func (char *ptr2)
    {
        ptr2 = new char[10];
        std::strcpy(ptr2, "Hello");
    }

    int main()
    {
        char *ptr1 = 0;
        func(ptr1);
    }

Okay, let's walk through this step by step.

1. char *ptr1 = 0;

Here we create a pointer and give it a value of 0.

    +---+
    | 0 |
    +---+
    ptr1

2. func(ptr1);

Now we call func and pass the value of ptr1--that is, 0. A new variable,
ptr2, is created, and given the value of 0.

    +---+
    | 0 |
    +---+
    ptr1

    +---+
    | 0 |
    +---+
    ptr2

3. ptr2 = new char[10];

Now we allocate a buffer with new[], and assign the address of the buffer to
ptr2 (let's pretend the address of the buffer is 0x38).

    +---+
    | 0 |
    +---+
    ptr1

    +------+ +---+---+---+---+---+---+---+---+---+---+
    | 0x38 |-----> | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
    +------+ +---+---+---+---+---+---+---+---+---+---+
    ptr2

4. std::strcpy(ptr2, "Hello");

Now we fill up the buffer we allocated.

    +---+
    | 0 |
    +---+
    ptr1

    +------+ +---+---+---+---+---+----+---+---+---+---+
    | 0x38 |-----> | H | e | l | l | o | \0 | ? | ? | ? | ? |
    +------+ +---+---+---+---+---+----+---+---+---+---+
    ptr2

5. Now, func ends. ptr2, being a local variable, is destroyed. The buffer
is not destroyed, because it was allocated on the free store with new.

    +---+
    | 0 |
    +---+
    ptr1

                   +---+---+---+---+---+----+---+---+---+---+
                   | H | e | l | l | o | \0 | ? | ? | ? | ? |
                   +---+---+---+---+---+----+---+---+---+---+

So now we're back in main. ptr1 was never changed to point to anything.
There is an allocated buffer, but there's nothing pointing to that buffer.
So we have a memory leak.

-- 
Russell Hanneken
eunaarxra@cbobk.pbz
Use ROT13 to decode my email address.


Relevant Pages

  • Re: Why does the &quot;Replace Array Subset&quot; double the used memory?
    ... data that's being modified is that LabVIEW has to allocate a buffer to ... Initialize Array function is always going to be the same, so LabVIEW ... don't always allocate a buffer for their use. ...
    (comp.lang.labview)
  • Re: Array.Resize or List<> or some other data structure
    ... The Listclass uses an array internally, and will do effectively the same operation as Array.Resize. ... If you can't process the bytes as they are read, but instead need to store them all up first, I would use a MemoryStream, and write to the MemoryStream as the bytes come in. ... With this alternative, you could either use a double- or triple-buffering scheme where you have two or three such buffers that are used in rotation, or you could just allocate a new buffer as needed, letting the used ones be garbage collected after they've been copied to the MemoryStream. ...
    (microsoft.public.dotnet.languages.csharp)
  • How can I write variable length byte array?
    ... I am in need of writing a variable amount of bytes to memmory (using ByteArrayInputStream) but can not allocate a fixed byte array since I do not know in advance how much will be received. ... What is the smartest way of making a dynamic buffer in memory, I am hoping for something better than having to copy a fixed based buffer into an ever growing final buffer. ...
    (comp.lang.java.help)
  • Re: Cons cell archaic!?
    ... from s-expression or XML or other syntax you keep the bloated array ... For using vectors to emulate lists that ... Allocate 2, move 1 element: ... What do you think of that algorithm? ...
    (comp.lang.lisp)
  • Storing/Retrieving TYPEs with ALLOCATABLE components (TR) (long)
    ... tBrd, including array descriptor of tEn )). ... Without previous DEALLOCATE, the allocate line fails at run time with message ... the fact that I'm loading an invalid descriptor tBrd%tEn from the file... ... status (which is not possible according to Standard, but then BINARY files ...
    (comp.lang.fortran)