By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,027 Members | 1,111 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,027 IT Pros & Developers. It's quick & easy.

Function like "Generic::List<String^>^ buildList(String^ inParm)" and avoiding warning C4172: returning address of local variable or temporary

P: n/a
Hi there,

I have a Managed C++ object (in a DLL) which has a method that is
defined like ...

Generic::List<String^>^ buildList(String^ inParm)

Now, when I compile it, I get "warning C4172: returning address of
local variable or temporary". In good old 'C', that would indicate
that a 'static' was missing from the declaration of the returned value.
How do I avoid this issue in Managed C++?

It does appear to work and fill the array - but I guess the data may
get garbage collected at any point and suddenly disappear.

Any help greatly appreciated.

Cheers,
Paul

(Functions below)
Calling Program
===========
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Configuration;

using XYZ.ABC;

namespace TestDriver
{
class Program
{
static void Main(string[] args)
{
tObject testObject = null;
Console.WriteLine("Start");

testObject = new tObject(7);

IList<StringreturnList = new List<String>();

returnList = testObject.buildList("information");

foreach (String thisValue in returnList)
{
Console.WriteLine("List item: [{0}]", thisValue);
}

Console.WriteLine("Finish");
Console.ReadLine();
}
}
}
AND
Called Object
==========

#include "stdafx.h"
#pragma once

using namespace System;
using namespace System::Globalization;
using namespace System::Collections::Generic;
using namespace System::Collections;
using namespace System::Runtime::InteropServices;

namespace XYZ {
namespace ABC {
public ref class tObject
{
private:
static int item_count = 0;
public:
tObject(int total_items) { item_count = total_items; }
virtual ~tObject() { item_count = 0; }

Generic::List<String^>^ buildList(String^ inParm)
{
int counter;
List<String^ResultList = gcnew List<String^>();

for(counter = 0; counter < item_count; counter++)
{
String^ Item;
Item = gcnew String("list item content " + inParm + " " + (counter
+ 1));
ResultList.Add(Item);
}

return %ResultList;
}
};
}
}

Oct 18 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a
rsa_net_newbie wrote:
{
int counter;
List<String^ResultList = gcnew List<String^>();
List<String^>^ ResultList = gcnew List<String^>();
for(counter = 0; counter < item_count; counter++)
{
String^ Item;
Item = gcnew String("list item content " + inParm + " " + (counter
+ 1));
ResultList.Add(Item);
ResultList->Add(Item);
}

return %ResultList;
return ResultList;

You can't return a reference to a temporary object that no longer exists
after the function returns.
}
};
}
}

Tom
Oct 18 '06 #2

P: n/a
Tamas has the exact correct fix. However, since this is "stack semantics"
and not actually memory on the stack, it will work reliably the way it is.
The only thing different is that with stack semantics for an IDisposable
type, the compiler calls Dispose at the end of the scope (like a using
block).
"Tamas Demjen" <td*****@yahoo.comwrote in message
news:eQ**************@TK2MSFTNGP04.phx.gbl...
rsa_net_newbie wrote:
>{
int counter;
List<String^ResultList = gcnew List<String^>();
List<String^>^ ResultList = gcnew List<String^>();
>for(counter = 0; counter < item_count; counter++)
{
String^ Item;
Item = gcnew String("list item content " + inParm + " " + (counter
+ 1));
ResultList.Add(Item);
ResultList->Add(Item);
>}

return %ResultList;
return ResultList;

You can't return a reference to a temporary object that no longer exists
after the function returns.
>}
};
}
}


Tom

Oct 18 '06 #3

P: n/a
Ben Voigt wrote:
Tamas has the exact correct fix. However, since this is "stack semantics"
and not actually memory on the stack, it will work reliably the way it is.
That's a good point. As long as you have a reference to an object, it
probably won't be garbage collected. On the other hand, if the type is
IDisposable, it gets disposed before the function returns.

Hmmmm... I don't really know whether the code in the original post is
perfectly safe or not. Generic::List<Tis not IDisposable, so it won't
be disposed on return that's for sure. I don't know if the compiler
generates code that lets the GC know that that local object is about to
have a life outside of the function. It looks like there's a moment when
the local ResultList handle is not being assigned to any existing
variable, which means it might be ninja GCed. One would have to see the
raw assembly output for that. Well, that warning would be enough to
discourage me anyway.

Tom
Oct 19 '06 #4

P: n/a

Tamas Demjen wrote:
rsa_net_newbie wrote:
{
int counter;
List<String^ResultList = gcnew List<String^>();
List<String^>^ ResultList = gcnew List<String^>();
for(counter = 0; counter < item_count; counter++)
{
String^ Item;
Item = gcnew String("list item content " + inParm + " " + (counter
+ 1));
ResultList.Add(Item);
ResultList->Add(Item);
}

return %ResultList;
return ResultList;

You can't return a reference to a temporary object that no longer exists
after the function returns.
}
};
}
}


Tom
Great - thanks.

Oct 19 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.