fut icon indicating copy to clipboard operation
fut copied to clipboard

Temporary values are not destructed in C, e.g. string interpolation leaks memory

Open yeputons opened this issue 3 years ago • 10 comments

Consider OpAddAssignString.ci:

		s2 += p + $"{p}" + s; //FAIL: cpp - should work with C++20

gets compiled to

	CiString_Assign(&s2, CiString_Format("%s%s%s%s", s2, p, p, s));

here, the result of CiString_Format is a result of malloc. It's passed to CiString_Assign and abandoned afterwards, leaking memory. This does not happen in C++ because temporary values are automatically destructed in C++, including std::string.

I assume there may be other instances where temporary objects are created and not immediately stored into variables.

yeputons avatar Oct 09 '21 09:10 yeputons

All tests are run in Travis CI. C, C++ and Swift tests are run with the Address Sanitizer and OpAddAssignString passes.

There's this line in the C translation of OpAddAssignString:

free(s2);

Why do you think it leaks memory?

pfusik avatar Oct 09 '21 10:10 pfusik

I'm sorry, I misread the example. Here is a simpler one:

public static class Test
{
	static void Foo(string x) {
	}
	public static void Run()
	{
	    int x;
	    Foo($"{x}");
	}
}

gets compiled to

static void Test_Foo(const char *x)
{
}

void Test_Run(void)
{
	int x;
	Test_Foo(CiString_Format("%d", x));
}

There is no free in this program at all.

yeputons avatar Oct 09 '21 10:10 yeputons

Yes, it's a known issue. I've just added a test and will fix it.

Interpolated strings are even worse when targetting C++, because they use C++20 <format>. Even though C++20 was ratified some time ago, clang only now starts implementing <format>.

pfusik avatar Oct 09 '21 10:10 pfusik

I believe the problem also exists with dynamic references in general. E.g. the following code:

class Foo {
}
public static class Test
{
	public static void Consume(Foo f) {}
	public static Foo# Create() { return new Foo(); }
	public static void Run() {
		Consume(Create());
	}
}

leaks memory and does not induce the Dynamically allocated objects must be assigned to a Foo# reference error, as Consume(new Foo()) would.

yeputons avatar Oct 09 '21 11:10 yeputons

cito cannot determine all the dangling reference scenarios. If it were easy, C and C++ compilers would do it, given five decades of their development. Consume(Create()) would be valid code if Create() stored the dynamic reference somewhere. The Create method itself is valid if used correctly.

pfusik avatar Oct 09 '21 12:10 pfusik

FWIW, I just learned that smart pointers are possible in C with GNU compilers: https://stackoverflow.com/questions/799825/smart-pointers-safe-memory-management-for-c

jedwards1211 avatar Oct 21 '21 18:10 jedwards1211

This issue is still unfixed for string concatination. The following code

string s1 = "1";
string s2 = "2";
string s3 = "3";
string s4 = "4";
string s5 = "5";
string() total = s1+s2+s3+s4+s5;

is transpiling to

const char *s1 = "1";
const char *s2 = "2";
const char *s3 = "3";
const char *s4 = "4";
const char *s5 = "5";
char *futemp0 = FuString_Format("%s%s", s1, s2);
char *futemp1 = FuString_Format("%s%s", FuString_Format("%s%s", s1, s2), s3);
char *futemp2 = FuString_Format("%s%s", FuString_Format("%s%s", FuString_Format("%s%s", s1, s2), s3), s4);
char *total = FuString_Format("%s%s", FuString_Format("%s%s", FuString_Format("%s%s", FuString_Format("%s%s", s1, s2), s3), s4), s5);

There are temporal variables declared correctly (futemp0, futemp1, futemp2), but this variables are not used in the FuString_Format() calls.

Timerix22 avatar Dec 22 '23 10:12 Timerix22

P.S. In the case of interpolation there is no such issue.

string() total = $"{s1}{s2}{s3}{s4}{s5}";

All FuString_Format() calls are merged in one:

char *total = FuString_Format("%s%s%s%s%s", s1, s2, s3, s4, s5);

Timerix22 avatar Dec 22 '23 10:12 Timerix22

@Timerix22 af1f308 fixes the concatenation of multiple strings.

I will work on the remaining cases.

pfusik avatar Jan 03 '24 15:01 pfusik

All cases reported here are now fixed.

pfusik avatar Mar 25 '24 12:03 pfusik