memory allocation

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guy's I'm lost, and don't know what to try.  I have a recursive function for deleting folder contents.  I'm allocating memory from the stack but it has stopped working when I decided not to use my own malloc function.

 

Have a look, maybe someone can give me some insight has to what to try!

 

void delete_folder_contents(FILEX * file){

	unsigned int root_address = file->cluster_nr;

	unsigned int source = file->dir_clusters->sequence;
	dir_insert_cluster(file);

	/**
	 * Using the GNU Compiler Collection (GCC) aligned (alignment) This
	 * attribute specifies a minimum alignment for the variable or
	 * structure field, measured in bytes. For example, the
	 * declaration: int x __attribute__ ( (aligned (16))) = 0;
	 * causes the compiler to allocate the global variable x on a
	 * 16-byte boundary.
	 */
	// Allocate Memory of the Stack for the recursive call
	unsigned char cache[cluster_size(file) + 1]__attribute__((aligned(32)));


	// perform DMA read of directory location to ensure the data is up-to-date
	dma_hardware_read(1, file->cluster_addr, sectors_per_cluster(file), cache, 0);
	
	//Code

when I use malloc to do it, it will work but it will only go 2 calls deep in the recursion.  For example:

 

		cache = rtos_malloc(cluster_size(file) + 32);
		cache = (unsigned char *)(((unsigned int)cache + 31) &~ 0x1f);

Anyone suggest what to do?

 

Thanks Freaks.

This topic has a solution.
Last Edited: Fri. Dec 24, 2021 - 04:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How is that "recursive"? I don't see any call to delete_folder_contents() from within delete_folder_contents()?? 

 

Also I see neither malloc nor free nor new nor delete so what has this got to do with the heap anyway? 

 

Or are you assuming we are all psychic and can see parts of the code you are not showing? 

 

One of the skills of training to be a professional engineer is learning how to relay a complete problem description to others who might be able to help. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see a couple of potential problems:

 

// Allocate Memory of the Stack for the recursive call
unsigned char cache[cluster_size(file) + 1]__attribute__((aligned(32)));

I may be exposing my ignorance here, but this looks like a stack variable whose size isn't known until runtime - the cluster_size(file) part. I don't think that works. I'm surprised this even compiles without errors.

 

// perform DMA read of directory location to ensure the data is up-to-date
dma_hardware_read(1, file->cluster_addr, sectors_per_cluster(file), cache, 0);

You're passing the address of your cache to some DMA function, then DMA will start running in the background. Meanwhile when your delete_folder_contents function returns, the region of stack where cache was located will get reclaimed and used for something else. But the DMA hardware doesn't know this, and it will keep stuffing bytes into that region of memory and overwrite something else, leading to a crash.

 

If you're passing a memory buffer address to DMA, then you either need to allocate memory from the heap and free it when the DMA is finished, or else use stack memory but don't return from your function until the DMA is complete. The second method probably defeats the purpose of using DMA.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bigmessowires wrote:

I may be exposing my ignorance here, but this looks like a stack variable whose size isn't known until runtime - the cluster_size(file) part. I don't think that works. I'm surprised this even compiles without errors.

 

C99 added support for variable length arrays (see the "Variable-length arrays" section of https://en.cppreference.com/w/c/...).

build-avr-gcc: avr-gcc build script

toolchain-avr-gcc: CMake toolchain for cross compiling for the AVR family of microcontrollers

avr-libcpp: C++ standard library partial implementation (C++17 only) for use with avr-gcc/avr-libc

picolibrary: C++ microcontroller driver/utility library targeted for use with resource constrained microcontrollers

picolibrary-microchip-megaavr: picolibrary HIL for megaAVR microcontrollers

picolibrary-microchip-megaavr0: picolibrary HIL for megaAVR 0-series microcontrollers

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bigmessowires wrote:

// Allocate Memory of the Stack for the recursive call unsigned char cache[cluster_size(file) + 1]__attribute__((aligned(32)));

I may be exposing my ignorance here, but this looks like a stack variable whose size isn't known until runtime - the cluster_size(file) part. I don't think that works. I'm surprised this even compiles without errors.

 

It does compile and does work.

 

This is a Variable Length Array - a VLA. It's been a feature of C language since 1999. It's been relegated to optional status in C11, but many compilers support it. 

 

Dessine-moi un mouton

Last Edited: Sun. Dec 19, 2021 - 07:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, so I succeeded at exposing my ignorance! yes

 

Then I would guess the source of OP's trouble is returning from the function while DMA hardware is still using the stack allocated buffer. But we need to see the rest of the code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying aligned_alloc but I get the following error during compilation.

aligned_alloc.o): In function `aligned_alloc':
aligned_alloc.c:(.text.aligned_alloc+0xa): undefined reference to `posix_memalign'

My guess is that I need a compiler flag.  Any ideas?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No you need a source file or a .a library that provides the posix_memalign() function

 

PS when I Google "posix_memalign undefined" I'm getting a ton of useful looking hits so it's not like you are on your own here

 

(I'd say about a half of all programming I do these days is with the benefit of "Stackoverflow"!) 

Last Edited: Sun. Dec 19, 2021 - 05:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

found the following function:

unsigned char * cache = (unsigned char *)memalign(32, cluster_size(file));

Same problem, it only works 2 deep in the recursion.  I've included the full code for the function below:

void delete_folder_contents(FILEX * file){

	unsigned int root_address = file->cluster_nr;

	unsigned int source = file->dir_clusters->sequence;
	dir_insert_cluster(file);

	/**
	 * Using the GNU Compiler Collection (GCC) aligned (alignment) This
	 * attribute specifies a minimum alignment for the variable or
	 * structure field, measured in bytes. For example, the
	 * declaration: int x __attribute__ ( (aligned (16))) = 0;
	 * causes the compiler to allocate the global variable x on a
	 * 16-byte boundary.
	 */
	// Allocate Memory of the Stack for the recursive call
	//unsigned char cache[cluster_size(file) + 1]__attribute__((aligned(32)));

	unsigned char * cache = (unsigned char *)memalign(32, cluster_size(file));

	// perform DMA read of directory location to ensure the data is up-to-date
	dma_hardware_read(1, file->cluster_addr, sectors_per_cluster(file), cache, 0);


	struct directory_entry     * directory = (struct directory_entry * )cache;
	struct stream_extension    * streamExt;
	struct file_name_extension * nameExt;


	char entry_name[255];
	unsigned char violation = 0;

	unsigned char entry_type = 0;

	// begin search
	while(1){

		if(directory->entry_type == DATAEXT){

			if(directory->file_attributes[0] == exFOLDER)
				entry_type = exFOLDER;
			else
				entry_type = exFILEX;

			streamExt = (struct stream_extension    *) directory + 1;


			// handle boundary violation!!!
			if(boudary_configure(file, cache, (unsigned char **)&streamExt, (unsigned char **)&directory, &violation) == 0)
				break;



			if(streamExt->entry_type == STREAMEXT){

				int name_length = streamExt->name_length;

				nameExt = (struct file_name_extension *) streamExt + 1;

				// handle boundary violation!!!
				if(boudary_configure(file, cache, (unsigned char **)&nameExt, (unsigned char **)&directory, &violation) == 0)
					break;



				if(nameExt->entry_type == FILEXEXT){

					unsigned char * ptr = nameExt->file_name;

					/** exFAT files have only one name, which is encoded as Unicode on disk and can have up to 255 characters. */
					int i;
					for(i = 0; i < name_length; i++){
						

						if(((i % 15) == 0) && (i != 0)){
							nameExt++;

							// handle boundary violation!!!
							if(boudary_configure(file, cache, (unsigned char **)&nameExt, (unsigned char **)&directory, &violation) == 0)
								break;


							if(nameExt->entry_type != FILEXEXT)
								goto escape;
							
							ptr = &nameExt->file_name[0];
							
						}entry_name[i] = * ptr; ptr += 2;
					}entry_name[i] = '\0';

					if(violation)
						prev_cluster(file);


					if(entry_type == exFOLDER){

						// Open Folder & Delete the contents
						exfat_open_folder(file, &entry_name[0]);

						/**
						 * Recursion: In programming terms, a recursive function can be defined as a routine that calls
						 * itself directly or indirectly. Using the recursive algorithm, certain problems can be solved
						 * quite easily. Towers of Hanoi (TOH) is one such programming exercise. Try to write an
						 * iterative algorithm for TOH. Moreover, every recursive program can be written using iterative
						 * methods.
						 */
						delete_folder_contents(file);
						exfat_return(file);

						c_printf("\r[m]Deleting %s", &entry_name[0]);
						exfat_delete_general_entry(file, &entry_name[0], root_address);
					}
					else{
						c_printf("\r[m]Deleting %s", &entry_name[0]);
						exfat_delete_general_entry(file, &entry_name[0], root_address);
					}

					if(violation)
						next_cluster(file);
				}
			}
		}
		directory++;

		// handle boundary violation!!!
		if(boudary_configure(file, cache, (unsigned char **)&directory, (unsigned char **)&directory, &violation) == 0)
			break;

		escape:
		violation = 0;
	}
	return_to_source(file, source);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

okay, been working on this.  It appears that

boudary_configure

is not doing what it is suppose to, it's late here in Ireland so I'm away to bed and I'll have a crack at it tomorrow.

 

Got it working sort off, the problem lay in another area and once again it was a problem allocating memory of the stack.  Hopefully get it sorted today.

Thanks Freaks.

Last Edited: Mon. Dec 20, 2021 - 03:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
No you need a source file or a .a library that provides the posix_memalign() function

I'm curious about which AVR model is running Posix.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

clawson wrote:
No you need a source file or a .a library that provides the posix_memalign() function

I'm curious about which AVR model is running Posix.

 

lol Not telling you!

 

Merry Christmas Lads!

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I decided to run the program in my RTOS and it works perfectly.  I'll take that has a win.