avoid use of malloc/free on a function

Hello,

A few month ago i made a function (thanks to the help of the forum) that take a char string and split it into a 2D array of char strings.
Now i would like to make this function without the need to continually call for malloc/realloc/free but using a pre-fixed buffer

maybe something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//g++  5.4.0
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <stdint.h>
#define print std::cout
#define endl "\n"

char **stringSplit(char ***dest_arr, size_t *len_dest_arr, const char *str, const char *delimiters)
{
    int str_len = strlen(str) + 1; // add null terminator
    char str_copy[str_len];        // we work on a copy
    strcpy(str_copy, str);
    bool allocate = false;

    if (*dest_arr == nullptr)
    {
        allocate = true;
    }

    if (allocate)
    {
        *dest_arr = (char **)malloc(sizeof(char *) * str_len); // over size
    }

    uint8_t counter = 0;                        // limited to 255 sub strings
    char *token = strtok(str_copy, delimiters); // split until first delimiter
    while (token != nullptr)
    {
        if (allocate)
        {
            (*dest_arr)[counter] = (char *)malloc(sizeof(char) * (strlen(token) + 1)); // add null terminator
        }
        strcpy((*dest_arr)[counter], token); // copy token to dest_array
        token = strtok(NULL, delimiters); // continue splitting
        counter++;
    }
    if (allocate)
    {
        *dest_arr = (char **)realloc(*dest_arr, sizeof(char *) * counter); // reallocate the right amount of memory
    }
    *len_dest_arr = counter; // save size
    return (*dest_arr);
}

int main()
{
    char log[] = "this is a test";
    char buffer[60][10];
    size_t buffer_len;
    stringSplit(&buffer, &buffer_len, log, " ");
}


but then, how could i call the function? because the above code would give me conversion errors, I tried almost everything this morning but I am not able to make it working
Last edited on
Remind us again why you can't use vector and string?
Don't do this. C++ has gone to great pains to provide variable length strings and vectors that are efficient and easy to use. Use the tools available:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <vector>
#include <string>

using std::vector;
using std::string;
using std::cin;
using std::cout;

vector<string> stringSplit(const string &src, const string &delimiters)
{
    vector<string> result;
    size_t start = 0;
    for (size_t end = src.find_first_of(delimiters, start);
	 end != string::npos;
	 start = end+1, end = src.find_first_of(delimiters, start)) {
	if (end != start) {
	    result.push_back(src.substr(start, end-start));
	}
    }
    if (start < src.size()) {
	result.push_back(src.substr(start));
    }
    return result;
}

int main()
{
    string line;
    while (getline(cin, line)) {
	vector<string> words = stringSplit(line, " \t");
	cout << line << '\n';
	cout << words.size() << " words\n";
	for (string &str : words) {
	    cout << '\t' << str << '\n';
	}
    }
}

Remind us again why you can't use vector and string?

I am on the arduino framework, which doesn't support stl out of the box, but i also just found some implementation (https://github.com/maniacbug/StandardCplusplus/blob/master/README.md )

Also really even if i am using the arduino framework to be more precise i am on the esp8266/esp32 which actually implemented the STL inside the core, so i guess i could use them
Last edited on
The changes were less then i through:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <Arduino.h>

#include <vector>
#include <string>
using std::string;
using std::vector;

vector<string> stringSplit(const string &src, const string &delimiters)
{
	vector<string> result;
	size_t start = 0;
	for (size_t end = src.find_first_of(delimiters, start);
		 end != string::npos;
		 start = end + 1, end = src.find_first_of(delimiters, start))
	{
		if (end != start)
		{
			result.push_back(src.substr(start, end - start));
		}
	}
	if (start < src.size())
	{
		result.push_back(src.substr(start));
	}
	return result;
}

void setup()
{
	Serial.begin(115200);
	delay(10);
	Serial.println("\nstl");
	delay(2000);
	string line = "test yes boh /http:1.1 ";
	Serial.println(line.c_str());
	vector<string> words = stringSplit(line, " \t");
	for (size_t n = 0; n < words.size(); n++)
	{
		Serial.println(words.at(n).c_str());
	}
	const char *const command = words.at(3).c_str();
	Serial.println(command);
}

void loop() {}


It is the first time i use string and vector, so this should be more memory safe?
Last edited on
Since you don't manually allocate memory, yes.

However just being memory safe doesn't mean the program won't crash. For example what is the significance of that magic number 3? What happens if words contains 3 or less elements?
Registered users can post here. Sign in or register to post.