I was implementing the little Java class to solve the string problem on Hackerrank:
Given the string, find its non-reducible form, considering one valid operation is to delete any pair of adjacent letters with same value.
Ex:
"aabcc" would become either "aab" or "bcc" after 1 operation.
However, I just want to mention about the block of code surrounding this error. Although I was able to solve the problem quite fine, I'm tempted by others to improve the solution's time performance by using the better approach of StringBuilder()
But I haven't figured out why the behavior of append() in my StringBuilder class could lead to the memory overflow or any sort of more complicated misbehavior.
Here's the code:
static String super_reduced_string(String s){
StringBuilder res = new StringBuilder();
for (int i = 1; i < s.length(); i++){
if (s.charAt(i-1) == s.charAt(i)){
/* waste so much memory leak!!! java.lang.OutOfMemoryError: Java heap space
//s = res.append(s.substring(0, i-1)).append(s.substring(i+1)).toString();
*/
s = s.substring(0, i-1) + s.substring(i+1);
i = 0;
}
}
//then check if it's non-empty, print it out
if (s.length() != 0){
return s;
}
return "Empty String";
}
The part where I commented out is the misbehavior mentioned above. Please kindly help me reason through this bug, and debug it! It shouldn't be that hard.
Just clear string builder after assigning to s.
s = res.append(s.substring(0, i-1)).append(s.substring(i+1)).toString();
res.setLength(0);
Related
I'm attempting to iterate a string but seem to be getting a weird access violation, The problem is caused when passing a value returned from JSON.stringify because the data seems to be read only, upon many attempts to use hacky methods to solve the issue I have not been successful in doing so.
I've tried copying the data, manually iterating the string and copying the string over to another variable, but the issue still remains the same no matter what I've tried.
The code below works flawlessly when a protected piece of data is not passed
xor_swap(keys, data)
{
for(var i = 0; i < data.length; i++)
data[i] ^= this.xor_key_exchange(keys, i);
return data.toString('utf8');
}
How ever when applying a parameter (for instance JSON.stringify), The data becomes protected and no matter what I seem to do the data seems to not be modifiable.
var enc = this.xor_swap(keys,JSON.stringify(data));
Please note that the input is completely correct, I have tested this many times.
Of-course the expected output is that the string should be iteratable, and after speaking to a few people who are very experienced in nodejs they can't seem to see why this problem is being caused.
I am not using strict-mode for anyone asking.
Thanks to anyone who can help me with this problem
In Javascript string is immutable. You cannot do the following
var a = 'hello';
a[1] = 'a' // try change 'e' to 'a', not possible
console.log(a)
JSON.stringify() returns a string which by definition is immutable.
So, this assignment here is invalid
data[i] ^= this.xor_key_exchange(keys, i);
thanks for your reply, I noticed that the conversion to a string is indeed immutable.
So I ended up solving this problem by simply converting the string to a buffer, completing my xor and then just converting the buffer directly back to a utf8 string again.
xor_swap(keys, data)
{
var buf = Buffer.from(data);
for(var i = 0; i < buf.length; i++)
buf[i] ^= Math.abs(this.xor_key_exchange(keys, i));
return buf.toString('utf8');
}
Thank you very much for your help
sorry for avoiding you guys
i have a problem with reverse function in circular linked list.
void reverse() {
int num = many;
node* current = head;
node* previous = 0;
while (num != 0) {
cout << "1" << '\t';
node* r = previous;
previous = current;
current = current->next;
previous->next = r;
num--;
}
head = previous;
}
in this func after 2 while sentence
problem comes up in line that current = current->next;
(exception throw : read access violation,
current was 0xDDDDDDDD)
how to handle it??
This is from Visual Studio trying to help you (and succeeding, IMO).
As Mark Ingraham pointed out in another answer a long time ago, Visual Studio's runtime library will fill a block of data with 0xDDDDDDDD when you release a block of heap memory.
So, although you haven't shown any code that's deleting from your list, if there is such code, that's probably the first place to look--at least at first glance, it looks like there's a fair chance that when you try erase a node from the list, you're deleting the memory the node lives in, but still leaving a pointer to that deleted memory.
It's also possible (but less likely, IMO) that you're just using memory without initializing it--and you happen to be hitting a block of memory that was previously allocated and then released back to the heap manager.
The bottom line, however, is that you don't "handle" the access violation. Instead, you need to find the bug in your code that's leading to the access violation happening, and fix it so that doesn't happen any more.
I have a doubt about a concurrent programming problem.
More specifically, we are working with the shared memory model(i.e. threads). The problem is: given a pool of N equivalent resources, there being the constraint that at a generic instant t there can only be one thread using a resource R, write a program that allocates these resources on demand to the threads that ask for them. To do this we have to use semaphores. Note that what these resources are and what the threads do with them is out of scope, the focus is on how the resources are managed and allocated. My professor gave us a C/Java-like pseudocode solution for the resources manager class:
class ResourcesManager {
semaphore mutex = 1;
semaphore availableResourcesSemaphore = N;
boolean available[N];
Resource resources[N];
public ResourcesManager(){
for(int i = 0; i < N; i++) {
available[i] = true;
resources[N] = new Resource();
}
}
public int acquireResource() {
int i = 0;
P(availableResourcesSemaphore);
P(mutex);
while(available[i]==false) i++;
available[i] = false;
V(mutex);
return i;
}
public void releaseResource(int i) {
P(mutex);
available[i] = true; //HERE IS THE PROBLEM
V(mutex);
V(availableResourcesSemaphore);
}
}
While I see that this solution works, there is something I don't get about the releaseResource(int i) method. Why is there the need of having the line marked with the comment "HERE IS THE PROBLEM":
available[i] = true;
executed in mutual exclusion? I have thought about it and to me it looks like nothing bad happens if we do otherwise.
What I mean is that while in the original solution we have:
P(mutex);
available[i] = true;
V(mutex);
we can replace these three lines simply with
available[i] = true;
and the solution is still correct.
Now, of course I see that mutual exclusion is needed when operating on the array "available" in the other method acquireResource(), and since the instruction
available[i] = true;
operates on the same variable it is more elegant and conceptually cleaner to operate on it in mutual exclusion too. On the other hand, as a beginner in concurrent programming, I don't think it's good to have mutual exclusion where it is not needed.
So am I right(the instruction can be executed without mutual exclusion) or am I missing something, and removing mutual exclusion causes some issues? One final note on the execution environment: it can be both uniprocessor or multiprocessor, meaning that the solution has to work for both cases. Thanks for your help!
As resources stated, Bakery algorithm is supposed to be deadlock free.
But when I tried to understand the pseudocode, I came up with a line which could raise a deadlock (according to my knowledge).
Reffering to the code below,
in Lock() function, we have a line saying
label[i] = max( label[0], ..., label[n-1] ) + 1;
What if two threads come to that state at the same time and since max is not atomic, two labels will get the same value?
Then since two labels have to same value, both threads with that labels will get the permission to go for the critical section at the same time. Wouldn't that occur a deadlock?
Tried myself best to explain the problem here. Comment if it is still not clear. Thanks .
class Bakery implements Lock {
volatile boolean[] flag;
volatile Label[] label;
public Bakery (int n) {
flag = new boolean[n];
label = new Label[n];
for (int i = 0; i < n; i++) {
flag[i] = false; label[i] = 0;
}
public void lock() {
flag[i] = true;
label[i] =max(label[0], ...,label[n-1])+1;
while ( $ k flag[k] && (label[i],i) > (label[k],k);
}
}
public void unlock() {
flag[i] = false;
}
Then since two labels have to same value, both threads with that labels will get the permission to go for the critical section at the same time. Wouldn't that occur a deadlock?
To begin with, you probably mean a race, not a deadlock.
However, no, there won't be a race here. If you look, there's the condition
(label[i],i) > (label[k],k)
and while this happens, the thread effectively busy-waits.
This means that even if label[i] is the same as label[k] (as both performed the max concurrently), the thread numbered higher will defer to the thread numbered lower.
(Arguably, this is a problem with the algorithm, as it inherently prioritizes the threads.)
I've got the following bit of code, which I've narrowed down to be causing a memory leak (that is, in Task Manager, the Private Working Set of memory increases with the same repeated input string). I understand the concepts of heaps and stacks for memory, as well as the general rules for avoiding memory leaks, but something somewhere is still going wrong:
while(!quit){
char* thebuffer = new char[210];
//checked the function, it isn't creating the leak
int size = FuncToObtainInputTextFromApp(thebuffer); //stored in thebuffer
string bufferstring = thebuffer;
int startlog = bufferstring.find("$");
int endlog = bufferstring.find("&");
string str_text="";
str_text = bufferstring.substr(startlog,endlog-startlog+1);
String^ str_text_m = gcnew String(str_text_m.c_str());
//some work done
delete str_text_m;
delete [] thebuffer;
}
The only thing I can think of is it might be the creation of 'string str_text' since it never goes out of scope since it just reloops in the while? If so, how would I resolve that? Defining it outside the while loop wouldn't solve it since it'd also remain in scope then too. Any help would be greatly appreciated.
You should use scope-bound resource management (also known as RAII), it's good practice in any case. Never allocate memory manually, keep it in an automatically allocated class that will clean up the resource for you in the destructor.
You code might read:
while(!quit)
{
// completely safe, no leaks possible
std::vector<char> thebuffer(210);
int size = FuncToObtainInputTextFromApp(&thebuffer[0]);
// you never used size, this should be better
string bufferstring(thebuffer, size);
// find does not return an int, but a size_t
std::size_t startlog = bufferstring.find("$");
std::size_t endlog = bufferstring.find("&");
// why was this split across two lines?
// there's also no checks to ensure the above find
// calls worked, be careful
string str_text = bufferstring.substr(startlog, endlog - startlog + 1);
// why copy the string into a String? why not construct
// this directly?
String^ str_text_m = gcnew String(str_text_m.c_str());
// ...
// don't really need to do that, I think,
// it's garbage collected for a reason
// delete str_text_m;
}
The point is, you won't get memory leaks if you're ensured your resources are freed by themselves. Maybe the garbage collector is causing your leak detector to mis-fire.
On a side note, your code seems to have lots of unnecessary copying, you might want to rethink how many times you copy the string around. (For example, find "$" and "&" while it's in the vector, and just copy from there into str_text, no need for an intermediate copy.)
Are you #using std, so that str_text's type is std::string? Maybe you meant to write -
String^ str_text_m = gcnew String(str_text.c_str());
(and not gcnew String(str_text_m.c_str()) ) ?
Most importantly, allocating a String (or any object) with gcnew is declaring that you will not be delete'ing it explicitly - you leave it up to the garbage collector. Not sure what happens if you do delete it (technically it's not even a pointer. Definitely does not reference anything on the CRT heap, where new/delete have power).
You can probably safely comment str_text_m's deletion. You can expect gradual memory increase (where the gcnew's accumulate) and sudden decreases (where the garbage collection kicks in) in some intervals.
Even better, you can probably reuse str_text_m, along the lines of -
String^ str_text_m = gcnew String();
while(!quit){
...
str_text_m = String(str_text.c_str());
...
}
I know its recommended to set the freed variable to NULL after deleting it just to prevent any invalid memory reference. May help, may not.
delete [] thebuffer;
thebuffer = NULL; // Clear a to prevent using invalid memory reference
There is a tool called DevPartner which can catch all memory leaks at runtime. If you have the pdb for your application this will give you the line numbers in your application where all memory leak has been observed.
This is best used for really big applications.