diff --git a/Outputs/CRT/CRT.hpp b/Outputs/CRT/CRT.hpp
index df78efe56..f64562800 100644
--- a/Outputs/CRT/CRT.hpp
+++ b/Outputs/CRT/CRT.hpp
@@ -243,7 +243,7 @@ class CRT {
 			that evaluates to the composite signal level as a function of a source buffer, sampling location, colour
 			carrier phase and amplitude.
 		*/
-		inline void set_composite_sampling_function(const char *shader)
+		inline void set_composite_sampling_function(const std::string &shader)
 		{
 			openGL_output_builder_.set_composite_sampling_function(shader);
 		}
@@ -261,7 +261,7 @@ class CRT {
 			* `vec2 coordinate` representing the source buffer location to sample from in the range [0, 1); and
 			* `vec2 icoordinate` representing the source buffer location to sample from as a pixel count, for easier multiple-pixels-per-byte unpacking.
 		*/
-		inline void set_rgb_sampling_function(const char *shader)
+		inline void set_rgb_sampling_function(const std::string &shader)
 		{
 			openGL_output_builder_.set_rgb_sampling_function(shader);
 		}
diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp
index 2b471fa3d..dc5166c9c 100644
--- a/Outputs/CRT/Internals/CRTOpenGL.cpp
+++ b/Outputs/CRT/Internals/CRTOpenGL.cpp
@@ -8,7 +8,6 @@
 #include "CRT.hpp"
 
 #include <cstdlib>
-#include <cstring>
 #include <cmath>
 
 #include "CRTOpenGL.hpp"
@@ -17,7 +16,8 @@
 
 using namespace Outputs::CRT;
 
-namespace {
+namespace
+{
 	static const GLenum source_data_texture_unit		= GL_TEXTURE0;
 	static const GLenum pixel_accumulation_texture_unit	= GL_TEXTURE1;
 
@@ -31,8 +31,6 @@ namespace {
 OpenGLOutputBuilder::OpenGLOutputBuilder(size_t bytes_per_pixel) :
 	visible_area_(Rect(0, 0, 1, 1)),
 	composite_src_output_y_(0),
-	composite_shader_(nullptr),
-	rgb_shader_(nullptr),
 	last_output_width_(0),
 	last_output_height_(0),
 	fence_(nullptr),
@@ -78,9 +76,6 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(size_t bytes_per_pixel) :
 OpenGLOutputBuilder::~OpenGLOutputBuilder()
 {
 	glDeleteVertexArrays(1, &output_vertex_array_);
-
-	free(composite_shader_);
-	free(rgb_shader_);
 }
 
 bool OpenGLOutputBuilder::get_is_television_output()
@@ -275,17 +270,17 @@ void OpenGLOutputBuilder::set_openGL_context_will_change(bool should_delete_reso
 	output_mutex_.unlock();
 }
 
-void OpenGLOutputBuilder::set_composite_sampling_function(const char *shader)
+void OpenGLOutputBuilder::set_composite_sampling_function(const std::string &shader)
 {
 	std::lock_guard<std::mutex> lock_guard(output_mutex_);
-	composite_shader_ = strdup(shader);
+	composite_shader_ = shader;
 	reset_all_OpenGL_state();
 }
 
-void OpenGLOutputBuilder::set_rgb_sampling_function(const char *shader)
+void OpenGLOutputBuilder::set_rgb_sampling_function(const std::string &shader)
 {
 	std::lock_guard<std::mutex> lock_guard(output_mutex_);
-	rgb_shader_ = strdup(shader);
+	rgb_shader_ = shader;
 	reset_all_OpenGL_state();
 }
 
@@ -321,7 +316,7 @@ void OpenGLOutputBuilder::prepare_composite_input_shaders()
 
 void OpenGLOutputBuilder::prepare_rgb_input_shaders()
 {
-	if(rgb_shader_)
+	if(rgb_shader_.size())
 	{
 		rgb_input_shader_program_ = OpenGL::IntermediateShader::make_rgb_source_shader(rgb_shader_);
 		rgb_input_shader_program_->set_source_texture_unit(source_data_texture_unit);
diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp
index b14d49e28..cb980b8fc 100644
--- a/Outputs/CRT/Internals/CRTOpenGL.hpp
+++ b/Outputs/CRT/Internals/CRTOpenGL.hpp
@@ -47,8 +47,8 @@ class OpenGLOutputBuilder {
 		Rect visible_area_;
 
 		// Other things the caller may have provided.
-		char *composite_shader_;
-		char *rgb_shader_;
+		std::string composite_shader_;
+		std::string rgb_shader_;
 
 		// Methods used by the OpenGL code
 		void prepare_output_shader();
@@ -148,8 +148,8 @@ class OpenGLOutputBuilder {
 
 		void draw_frame(unsigned int output_width, unsigned int output_height, bool only_if_dirty);
 		void set_openGL_context_will_change(bool should_delete_resources);
-		void set_composite_sampling_function(const char *shader);
-		void set_rgb_sampling_function(const char *shader);
+		void set_composite_sampling_function(const std::string &shader);
+		void set_rgb_sampling_function(const std::string &shader);
 		void set_output_device(OutputDevice output_device);
 		void set_timing(unsigned int input_frequency, unsigned int cycles_per_line, unsigned int height_of_display, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider);
 };
diff --git a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp
index 870eef24f..40c8bebbe 100644
--- a/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp
+++ b/Outputs/CRT/Internals/Shaders/IntermediateShader.cpp
@@ -26,7 +26,7 @@ namespace {
 	};
 }
 
-std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const char *fragment_shader, bool use_usampler, bool input_is_inputPosition)
+std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const std::string &fragment_shader, bool use_usampler, bool input_is_inputPosition)
 {
 	const char *sampler_type = use_usampler ? "usampler2D" : "sampler2D";
 	const char *input_variable = input_is_inputPosition ? "inputPosition" : "outputPosition";
@@ -111,12 +111,13 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const char *
 	return shader;
 }
 
-std::unique_ptr<IntermediateShader> IntermediateShader::make_source_conversion_shader(const char *composite_shader, const char *rgb_shader)
+std::unique_ptr<IntermediateShader> IntermediateShader::make_source_conversion_shader(const std::string &composite_shader, const std::string &rgb_shader)
 {
-	char *composite_sample = (char *)composite_shader;
-	if(!composite_sample)
+	char *derived_composite_sample = nullptr;
+	const char *composite_sample = composite_shader.c_str();
+	if(!composite_shader.size())
 	{
-		asprintf(&composite_sample,
+		asprintf(&derived_composite_sample,
 			"%s\n"
 			"uniform mat3 rgbToLumaChroma;"
 			"float composite_sample(usampler2D texID, vec2 coordinate, vec2 iCoordinate, float phase, float amplitude)"
@@ -126,7 +127,8 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_source_conversion_s
 				"vec2 quadrature = vec2(cos(phase), -sin(phase)) * amplitude;"
 				"return dot(lumaChromaColour, vec3(1.0 - amplitude, quadrature));"
 			"}",
-			rgb_shader);
+			rgb_shader.c_str());
+		composite_sample = derived_composite_sample;
 	}
 
 	char *fragment_shader;
@@ -148,7 +150,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_source_conversion_s
 			"fragColour = vec4(composite_sample(texID, inputPositionsVarying[5], iInputPositionVarying, phaseAndAmplitudeVarying.x, phaseAndAmplitudeVarying.y));"
 		"}"
 	, composite_sample);
-	if(!composite_shader) free(composite_sample);
+	free(derived_composite_sample);
 
 	std::unique_ptr<IntermediateShader> shader = make_shader(fragment_shader, true, true);
 	free(fragment_shader);
@@ -156,7 +158,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_source_conversion_s
 	return shader;
 }
 
-std::unique_ptr<IntermediateShader> IntermediateShader::make_rgb_source_shader(const char *rgb_shader)
+std::unique_ptr<IntermediateShader> IntermediateShader::make_rgb_source_shader(const std::string &rgb_shader)
 {
 	char *fragment_shader;
 	asprintf(&fragment_shader,
@@ -176,7 +178,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_rgb_source_shader(c
 		"{"
 			"fragColour = rgb_sample(texID, inputPositionsVarying[5], iInputPositionVarying);"
 		"}"
-	, rgb_shader);
+	, rgb_shader.c_str());
 
 	std::unique_ptr<IntermediateShader> shader = make_shader(fragment_shader, true, true);
 	free(fragment_shader);
diff --git a/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp b/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp
index 13dedc2c4..fc79e5fd7 100644
--- a/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp
+++ b/Outputs/CRT/Internals/Shaders/IntermediateShader.hpp
@@ -25,13 +25,13 @@ public:
 		converting them to single-channel composite values using @c composite_shader if supplied
 		or @c rgb_shader and a reference composite conversion if @c composite_shader is @c nullptr.
 	*/
-	static std::unique_ptr<IntermediateShader> make_source_conversion_shader(const char *composite_shader, const char *rgb_shader);
+	static std::unique_ptr<IntermediateShader> make_source_conversion_shader(const std::string &composite_shader, const std::string &rgb_shader);
 
 	/*!
 		Constructs and returns an intermediate shader that will take runs from the inputPositions,
 		converting them to RGB values using @c rgb_shader.
 	*/
-	static std::unique_ptr<IntermediateShader> make_rgb_source_shader(const char *rgb_shader);
+	static std::unique_ptr<IntermediateShader> make_rgb_source_shader(const std::string &rgb_shader);
 
 	/*!
 		Constructs and returns an intermediate shader that will read composite samples from the R channel,
@@ -95,7 +95,7 @@ public:
 	void set_is_double_height(bool is_double_height, float input_offset = 0.0f, float output_offset = 0.0f);
 
 private:
-	static std::unique_ptr<IntermediateShader> make_shader(const char *fragment_shader, bool use_usampler, bool input_is_inputPosition);
+	static std::unique_ptr<IntermediateShader> make_shader(const std::string &fragment_shader, bool use_usampler, bool input_is_inputPosition);
 };
 
 }
diff --git a/Outputs/CRT/Internals/Shaders/Shader.cpp b/Outputs/CRT/Internals/Shaders/Shader.cpp
index 4dc5fa90d..ddc723c4a 100644
--- a/Outputs/CRT/Internals/Shaders/Shader.cpp
+++ b/Outputs/CRT/Internals/Shaders/Shader.cpp
@@ -8,22 +8,23 @@
 
 #include "Shader.hpp"
 
-#include <stdlib.h>
 #include <stdio.h>
 
 using namespace OpenGL;
 
-namespace {
+namespace
+{
 	Shader *bound_shader = nullptr;
 }
 
-GLuint Shader::compile_shader(const char *source, GLenum type)
+GLuint Shader::compile_shader(const std::string &source, GLenum type)
 {
 	GLuint shader = glCreateShader(type);
-	glShaderSource(shader, 1, &source, NULL);
+	const char *c_str = source.c_str();
+	glShaderSource(shader, 1, &c_str, NULL);
 	glCompileShader(shader);
 
-#if defined(DEBUG)
+#ifdef DEBUG
 	GLint isCompiled = 0;
 	glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
 	if(isCompiled == GL_FALSE)
@@ -31,10 +32,10 @@ GLuint Shader::compile_shader(const char *source, GLenum type)
 		GLint logLength;
 		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
 		if(logLength > 0) {
-			GLchar *log = (GLchar *)malloc((size_t)logLength);
+			GLchar *log = new GLchar[logLength];
 			glGetShaderInfoLog(shader, logLength, &logLength, log);
 			printf("Compile log:\n%s\n", log);
-			free(log);
+			delete[] log;
 		}
 
 		throw (type == GL_VERTEX_SHADER) ? VertexShaderCompilationError : FragmentShaderCompilationError;
@@ -44,7 +45,7 @@ GLuint Shader::compile_shader(const char *source, GLenum type)
 	return shader;
 }
 
-Shader::Shader(const char *vertex_shader, const char *fragment_shader, const AttributeBinding *attribute_bindings)
+Shader::Shader(const std::string &vertex_shader, const std::string &fragment_shader, const AttributeBinding *attribute_bindings)
 {
 	shader_program_ = glCreateProgram();
 	GLuint vertex = compile_shader(vertex_shader, GL_VERTEX_SHADER);
@@ -64,7 +65,7 @@ Shader::Shader(const char *vertex_shader, const char *fragment_shader, const Att
 
 	glLinkProgram(shader_program_);
 
-#if defined(DEBUG)
+#ifdef DEBUG
 	GLint didLink = 0;
 	glGetProgramiv(shader_program_, GL_LINK_STATUS, &didLink);
 	if(didLink == GL_FALSE)
@@ -72,10 +73,10 @@ Shader::Shader(const char *vertex_shader, const char *fragment_shader, const Att
 		GLint logLength;
 		glGetProgramiv(shader_program_, GL_INFO_LOG_LENGTH, &logLength);
 		if(logLength > 0) {
-			GLchar *log = (GLchar *)malloc((size_t)logLength);
+			GLchar *log = new GLchar[logLength];
 			glGetProgramInfoLog(shader_program_, logLength, &logLength, log);
 			printf("Link log:\n%s\n", log);
-			free(log);
+			delete[] log;
 		}
 		throw ProgramLinkageError;
 	}
diff --git a/Outputs/CRT/Internals/Shaders/Shader.hpp b/Outputs/CRT/Internals/Shaders/Shader.hpp
index ba95daf7c..f2afa3ab9 100644
--- a/Outputs/CRT/Internals/Shaders/Shader.hpp
+++ b/Outputs/CRT/Internals/Shaders/Shader.hpp
@@ -41,7 +41,7 @@ public:
 		@param fragment_shader The fragment shader source code.
 		@param attribute_bindings Either @c nullptr or an array terminated by an entry with a @c nullptr-name of attribute bindings.
 	*/
-	Shader(const char *vertex_shader, const char *fragment_shader, const AttributeBinding *attribute_bindings);
+	Shader(const std::string &vertex_shader, const std::string &fragment_shader, const AttributeBinding *attribute_bindings);
 	~Shader();
 
 	/*!
@@ -106,7 +106,7 @@ public:
 	void set_uniform_matrix(const std::string &name, GLint size, GLsizei count, bool transpose, const GLfloat *values);
 
 private:
-	GLuint compile_shader(const char *source, GLenum type);
+	GLuint compile_shader(const std::string &source, GLenum type);
 	GLuint shader_program_;
 
 	void flush_functions();