Anhängen an std::string schlägt fehl(malloc.c:3096: sYSMALLOc: Assertion...)



  • Tag,

    ich programmiere einen Server und einen HTTP-Parser in C++. Beim Schreiben der empfangenen Daten in einen std::string wird immer beim 251 Request eine Fehlermeldung ausgegeben (Zeile 118).
    Warum entsteht der Fehler und wie kann ich ihn beheben?

    server: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
    

    server.cpp

    #include <errno.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <iostream>
    #include <sys/time.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <stdlib.h>
    #include <string>
    #include "http_parser.cpp"
    
    #define SOCK_RECV_BUFFER 128
    
    class AIOSocket {
    
    	int sock, lasterror, maxclients, active, highest;
    	struct sockaddr_in clientname;
    	fd_set active_set, read_set;
        public:
    	AIOSocket(int port, int type=AF_INET, int domain=SOCK_STREAM) {	
    		lasterror = 0;
    		maxclients = 3;
    		active = -1;
    		sock = socket(type, domain, NULL);
    		if(sock < 0) {
    			lasterror = 1;
    		}
    		highest = sock;
    		struct sockaddr_in server_address;
    		server_address.sin_family = type;
    		server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    		server_address.sin_port = htons(port);
    		if(bind(sock, reinterpret_cast<struct sockaddr *>(&server_address), sizeof(server_address)) < 0) {
    			lasterror = 2;
    		}
    	}
    	~AIOSocket() {
    		close(sock);
    	}
    
    	void SetMaxClients(int mc) { maxclients = mc; }
    
    	int Fault() {
    		int ret = lasterror;
    		lasterror = 0;
    		return ret;
    	}
    
    	int Listen() {
    		int r = listen(sock, maxclients) < 0 ? 1 : 0;
    		FD_ZERO(&active_set);
    		FD_SET(sock, &active_set);
    		return r;
    	}
    
    	int Select(void callback(AIOSocket*), int timeoutS=NULL) {
    
    		read_set = active_set;
    		active = -1;
    		int selectState;
    		if(timeoutS) {
    			struct timeval timeout;
    			timeout.tv_sec = timeoutS;
    			timeout.tv_usec = 0;
    			selectState = select(highest+1, &read_set, NULL, NULL, &timeout);
    		}
    		else selectState = select(highest+1, &read_set, NULL, NULL, NULL);
    		if(selectState < 0)
    			return 1;
    		for(int i=0; i<highest+1; i++) {
    			if(FD_ISSET(i, &read_set)) {
    				if(i==sock) {
    					int client;
    					socklen_t size = sizeof(clientname);
    					client = accept(sock, (struct sockaddr*) &clientname, &size);
    					if(client < 0)
    						return 1;
    					if(client > highest)
    						highest = client;
    					FD_SET(client, &active_set);
    				}
    				else {
    					active = i;
    					if(callback) {
    						callback(this);
    					}
    				}
    			}
    		}
    		return 0;
    	}
    
    	sockaddr_in* ClientInfo() {
    		return &clientname;
    	}
    
    	int GetClient() {
    		return active;
    	}
    
    	const char *Read() {
    		char bu[SOCK_RECV_BUFFER];
    		int size = 0;
    		int recv;
    		std::string request("");
    
    		while(true) {
    			recv = read(active, &bu, SOCK_RECV_BUFFER-1);
    			if(recv < 0) {
    				lasterror = 3;
    				return 0;
    			}
    			if(recv > 0) {
    				size += recv;
    				for(int i=0; i<recv; i++) {
    					if(bu[i] != 0) {
    						request += bu[i]; // HIER ENTSTEHT DER FEHLER
    					}
    				}
    			}
    			if(recv < SOCK_RECV_BUFFER-1) {
    				char *r = new char[size];
    				strcpy(r, request.c_str());
    				return r;
    			}
    		}
    
    	}
    
    	void Send(const char *msg) {
    		send(active, msg, strlen(msg), NULL);
    	}
    
    	void CloseClient() {
    		close(active);
    		FD_CLR(active, &active_set);
    	}
    
    };
    
    void HandleClient(AIOSocket *sock) {
    	int b;
    	sockaddr_in *client = sock->ClientInfo();
    	std::cout << inet_ntoa(client->sin_addr) << ":" << ntohs(client->sin_port) << std::endl;
    
    	HttpRequest req(sock->Read());
    	req.Parse();
    
    	sock->Send("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: 5\r\n\r\ntäst");
    	sock->CloseClient();
    
    };
    
    /*int utf8strlen(char *str) {
    	int i = 0, j=0;
    	while(str[i]) {
    		if((str[i] & 0xc0) != 0x80) j++;
    		i++;
    	}
    	return j;
    }*/
    
    int main(int argc, char *argv[]) {
    
    	int port=5555;
    	if(argc >= 2)
    		port = atoi(argv[1]);
    
    	AIOSocket mysock(port);
    	if(mysock.Fault() != 0) {
    		std::cerr << "Error: " << errno << std::endl;
    		exit(EXIT_FAILURE);
    	}
    	if(mysock.Listen() != 0) {
    		std::cerr << "Error: " << errno << std::endl;
    		exit(EXIT_FAILURE);
    	}
    
    	while(true) {
    		mysock.Select(HandleClient, 10);
    	}
    
    }
    

    http_parser.cpp

    #include <map>
    #include <stdio.h>
    
    class HttpRequest {
    	char *request_str;
    	float http_version;
    	char *http_method;
    	char *http_uri;
    	std::map<char*, char*> headers;
    
    	char* ParseFirstLine(char *request_string) {
    
    		int len = 0;
    		while(request_string[len++] != ' ');
    		http_method = new char[len];
    		strncpy(http_method, request_string, len-1);
    		http_method[len] = '\0';
    		request_string+=len;
    
    		len = 0;
    		while(request_string[len++] != ' ');
    		http_uri = new char[len];
    		strncpy(http_uri, request_string, len-1);
    		http_uri[len] = '\0';
    		request_string+=len + 5;
    
    		int lv = 0;
    		float version=0, version_r=0;
    		do {
    			version *= (lv++)*10;
    			version += request_string[0] - '0';
    		} while((++request_string)[0] != '.');
    		request_string++;
    		lv = 0;
    		do {
    			version_r *= (lv++)*10;
    			version_r += request_string[0] - '0';
    		} while((++request_string)[0] != '\r');
    
    		http_version = version + (version_r/10);
    
    		return (request_string+2);
    	}
    
    	int ParseHeaders(char *request_string) {
    		int len=0;
    		while(request_string[++len]) {
    			if(request_string[len] == ':') {
    
    				char *header = new char[len];
    				strncpy(header, request_string, len);
    				request_string += len+2;
    				header[len] = '\0';
    				len = 0;
    
    				while(request_string[++len] != '\r');
    
    				char *value = new char[len];
    				strncpy(value, request_string, len);
    				request_string += len+2;
    				value[len] = '\0';
    				len = 0;
    
    				headers.insert(std::pair<char*,char*>(header,value));
    			}
    		}
    	}
    
        public:
    
    	HttpRequest(const char *r) {
    		request_str = const_cast<char*>(r);
    	}
    	HttpRequest(char *r) {
    		request_str = r;
    		http_method = NULL;
    		http_uri = NULL;
    	}
    	~HttpRequest() {
    		if(http_method)
    			delete http_method;
    		if(http_uri)
    			delete http_uri;
    		if(request_str) {
    			delete request_str;
    		}
    	}
    
    	char *GetHeader(char *header) {
    		return headers[header];
    	}
    	char *GetHeader(const char *header) {
    		return GetHeader(const_cast<char*>(header));
    	}
    
    	int Parse() {
    		char *request_headers = ParseFirstLine(request_str);
    		ParseHeaders(request_headers);
    
    		return 0;
    	}
    
    	int Version(void) {
    		return http_version;
    	}
    	char *Method(void) {
    		return http_method;
    	}
    	char *Uri(void) {
    		return http_uri;
    	}
    };
    

    Kompiliert mit gcc4.4.3 auf Ubuntu 10.04



  • Laut Google ist da wohl was im speicher defekt. Schau dir mal mit valgrind an, ob du bei der Speicherverwaltung Fehler machst. Hier hats geholfen...


Log in to reply