Google Interview Question for Software Engineers


Country: United States
Interview Type: Phone Interview




Comment hidden because of low score. Click to expand.
0
of 2 vote

do malloc of size (sizeInBytes+sizeAlignment), then from the starting pointer, find the first address that %sizeAlignment gives you 0.

if size is 1000 and alignment is 64, and malloc gives you a pointer at location 129 for example, it will extend from address 129 to 1093. From 129, we need to find the first pointer that %64 is 0, so we do (129/64 + 1)*64 = 192. From 192, we mark this as the beginning of the allocated space, and we mark 192 + 1000 -> 1192 as the end of the block.
Not sure how to stop memory from being used though.

To delete, Keep track of this distance from the new pointer to the original malloc pointer address.

- SK September 05, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Do not understand how to deal with the 2nd parameter: size_t alignment. Can anyone explain?

- cdhsiung September 06, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

It's got to do with pointer's memory value. A pointer points to any byte value in memory. 64 bit alignment means the pointer should be pointing to a value that is divisible by 8. You get 8 by dividing 64/8. 64 is bits, you have to convert that to bytes. Read up more about C++ memory alignment. For example it helps pack member data in classes.

- thewhatwhat September 09, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

void * aligned_alloc(size_t size, int alignment_bits) {
        //reserve requested size plus: space for allocating a pointer plus spac$
        size_t sz=size+sizeof(void*)+(1<<alignment_bits);
        char *p0=(char*)malloc(sz);
        if (p0==0) return 0;
        //advance p to its maximum value
        char* p=p0+sizeof(void*)+(1<<alignment_bits);
        //cut less significant bits to achieve alignment
        p=(char*)((uintptr_t)p&(uintptr_t)~((1<<alignment_bits)-1));
        //store real addresss in the previous address
        *(void**)(p-sizeof(void*))=p0;
        return (void*)p;
}

void alignned_free(void* p) {
        free((char*)p-sizeof(void*));
}

- mayorga.geek September 06, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This is good solution

- 0xF4 September 07, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

void* does not support arithmetic, maybe you mean this code:

void *alignAllocate(size_t size, size_t align) {
	int offset = sizeof(void*) + align - 1;
	void *rawPtr = malloc(size + offset);
	if (rawPtr == nullptr)
		return nullptr;

	char *ans = (char*)rawPtr + sizeof(void*);
	ans = (char*)(long(ans + align - 1) & ~(align - 1));
	*((void**)ans - 1) = rawPtr;

	return ans;
}

void alignFree(void *ptr) {
	void *rawPtr = *((void**)ptr - 1);
	free(rawPtr);
}

- malinbupt September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

you're right malinbupt, thank you.

here is my correction:

void * aligned_alloc(size_t size, int alignment_bits) {
        //reserve requested size plus: space for allocating a pointer plus spac$
        size_t sz=size+sizeof(void*)+(1<<alignment_bits);
        char *p0=(char*)malloc(sz);
        if (p0==0) return 0;
        //advance p to its maximum value
        char* p=p0+sizeof(void*)+(1<<alignment_bits);
        //cut less significant bits to achieve alignment
        p=(char*)((uintptr_t)p&(uintptr_t)~((1<<alignment_bits)-1));
        //store real addresss in the previous address
        *(void**)(p-sizeof(void*))=p0;
        return (void*)p;
}

void alignned_free(void* p) {
        free((char*)p-sizeof(void*));
}

- mayorga.geek September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Should work for 32/64 bit env.

struct H { void *op; };

typedef void* voidptr;
typedef unsigned char* byteptr;

void* aAlloc(size_t l, size_t a)
{	
	auto  a0 = a >> 3;
	voidptr p0 = std::malloc(sizeof(H) + l + a0);
	
	byteptr p = (byteptr)(p0) + sizeof(H);
	p += (uintptr_t)p & (a0 - 1);

	((H*)p - 1)->op = p0;
	return (void*)p;
}

void afree(void *p)
{
	std::free(((H*)p - 1)->op);
}

- AT September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 3 vote

#include <list>
#include <unordered_map>
#include <cstdlib>

std::unordered_map<void*, void*> _alignedToUnaligned;

void * alignedAllocate(size_t sizeInBytes, size_t alignment)
{
    if(sizeInBytes == 0)
        return nullptr;
    if(alignment == 0)
        alignment = 1;
    void* unaligned = malloc(sizeInBytes + alignment - 1);
    void* aligned = unaligned;
    auto offset = (size_t) unaligned % alignment;
    if(offset != 0)
    {
        aligned = (void*) ((size_t)aligned + alignment - offset);
    }
    _alignedToUnaligned[aligned] = unaligned;
    return aligned;
}

int alignedDeallocate(void* alignedPtr)
{
    auto iter = _alignedToUnaligned.find(alignedPtr);
    if(iter == _alignedToUnaligned.end())
    {
        return -1;
    }
    auto unaligned = iter->second;
    _alignedToUnaligned.erase(iter);
    free(unaligned);
    return 0;
}

void alignedDeallocate(std::list<void*> alignedPtrs)
{
    for(auto ptr : alignedPtrs)
    {
        alignedDeallocate(ptr);
    }
}

- u September 05, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I wrote similar code except I used new instead of malloc. I did a new with char* and cast to void* but apparently I did something wrong cause I didn't get selected.

- thewhatwhat September 06, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

usage of map is a clear overkill here

- 0xF4 September 07, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

1. you do not handle the situation when malloc returns NULL pointer
2. allocating (sizeInBytes + alignment) bytes right at the beginning could be inefficient if alignment is large. Suppose, sizeInBytes = 1024 and alignment = 1024. Then you'll waste 1024 bytes! While, it's quite likely that malloc already allocates an 1024-byte aligned chunk in this case.

Therefore, it probably makes sense:
- use some memory pool for allocations (to save on fragmentation)
- first issue 'malloc' with original size. Then if it's not properly aligned (or if the alignment is non-standard, e.g., like 127 bytes), use realloc with 'bytes + alignment' size

- anon October 01, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

1. you do not handle the situation when malloc returns NULL pointer
2. allocating (sizeInBytes + alignment) bytes right at the beginning could be inefficient if alignment is large. Suppose, sizeInBytes = 1024 and alignment = 1024. Then you'll waste 1024 bytes! While, it's quite likely that malloc already allocates an 1024-byte aligned chunk in this case.

Therefore, it probably makes sense:
- use some memory pool for allocations (to save on fragmentation)
- first issue 'malloc' with original size. Then if it's not properly aligned (or if the alignment is non-standard, e.g., like 127 bytes), use realloc with 'bytes + alignment' size

- anon October 01, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

1. you do not handle the situation when malloc returns NULL pointer
2. allocating (sizeInBytes + alignment) bytes right at the beginning could be inefficient if alignment is large. Suppose, sizeInBytes = 1024 and alignment = 1024. Then you'll waste 1024 bytes! While, it's quite likely that malloc already allocates an 1024-byte aligned chunk in this case.

Therefore, it probably makes sense:
- use some memory pool for allocations (to save on fragmentation)
- first issue 'malloc' with original size. Then if it's not properly aligned (or if the alignment is non-standard, e.g., like 127 bytes), use realloc with 'bytes + alignment' size

- pavel.em October 01, 2015 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 vote

void * alignedMalloc(size_t size, size_t alignment)
{
	size_t bytes = alignment / 8;
	return malloc(bytes + (size % bytes) / bytes);
}

void alignedFree(void **p)
{
	std::free(*p);
	*p = nullptr;
}

- Teh Kok How September 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

void * alignedMalloc(size_t size, size_t alignment)
{
	size_t bytes = alignment / 8;
	return malloc(size + (size % bytes) / bytes);
}

void alignedFree(void **p)
{
	std::free(*p);
	*p = nullptr;
}

- Teh Kok How September 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

1.- you are adjusting the requested size instead of the memory address returned by malloc
2. why you pass void** in alignedFree instead of the same value that alignedMalloc returns?

- mayorga.geek September 11, 2015 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More