WTF is going on! Corrupt value that is never assigned

FoxyBrown via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jul 13 11:22:34 PDT 2017


The following code is pretty screwed up, even though it doesn't 
look like it. I have a buf, a simple malloc which hold the 
results of a win32 call. I am then trying to copy over the data 
in buf to a D struct.

But when copying the strings, the buf location changes, screwing 
up the copying process. It shouldn't happen, buf never changes 
value anywhere except the first malloc(which is once). Somehow it 
is getting changed, but where?

The specific win32 or style is irrelevant, I am talking either 
about a bug or some subtle D thing because the code makes sense. 
(Fill Buf, iterate through buffer copying over to D values).

I've ran in to this before, D does something fishy and it wastes 
hours upon hours trying to track done some stupid little thing it 
does.

The buf value changes when calling cstr2dstr but I've had it with 
other values to(any function call such as to!string, etc seems to 
trigger it).




struct ServiceData
{
     wstring Name;
     wstring LongName;
     int Type;
     int State;
     int ControlsAccepted;
     int Win32ExitCode;
     int SpecificExitCode;
     int CheckPoint;
     int WaitHint;
     int ProcessId;
     int Flags;
}

auto cstr2dstr(wchar* cstr)
{
	import std.array;
	auto str = appender!wstring;
	auto len = lstrlen(cstr);
	str.reserve(len);
	
	for(int i = 0; i < len; i++)
		str.put(cstr[i]);

	return str.data;
}


auto EnumServices()
{
	import core.stdc.stdlib, std.traits;
	ServiceData[] servicesList;

	auto buf = malloc(50000); // Gets changed later, even though 
never an assignment
	auto buf2 = buf; // does not change
     auto schSCManager = OpenSCManager(null, null, 
SC_MANAGER_ALL_ACCESS);
     if (NULL == schSCManager)
     {
         print("OpenSCManager failed (%d)\n", GetLastError());
         return servicesList;
     }
		
	DWORD dwBytesNeeded, dwCount, lpResumeHandle, resume, totalCount;
	auto servicesType = (SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER 
| SERVICE_KERNEL_DRIVER | SERVICE_WIN32 | 
SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS);

	int cnt = 0;		
	auto res = 0;
	do
     {
		// Manually copy over data, this is because EnumSErvicesStatus 
adds data at end of array for some odd ball reason making it 
difficult to build the correct array sequentially
		for(int i = 0; i < dwCount; i++)
		{
			ENUM_SERVICE_STATUS_PROCESSW x;
			ServiceData d;
			auto s = cast(ENUM_SERVICE_STATUS_PROCESSW*)(buf + 
i*ENUM_SERVICE_STATUS_PROCESSW.sizeof);
//                    before buf is of correct value
			d.Name = cstr2dstr(s.lpServiceName);
//                    after buf is invalid, yet buf is never 
assigned

		}

		
		res = EnumServicesStatusExW(schSCManager, 
SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, servicesType, 
SERVICE_STATE_ALL, cast(ubyte*)buf, 50000, &dwBytesNeeded, 
&dwCount, &resume, cast(const(char)*)null);
		if (ERROR_MORE_DATA != GetLastError()) { print("Error 
enumerating services."); break; } 				
	} while (res == 0);

	
	for(int i = 0; i < totalCount; i++)
	{
		auto s = servicesList[i];
		writeln(s.Name, " - ", s.LongName, " - ", s.Type, " = ", 
s.State);
	}


	return servicesList;
}


More information about the Digitalmars-d-learn mailing list